@@ -18,8 +18,17 @@ use log::debug;
18
18
/// extending `HandlerFlags`, accessed via `self.handler.flags`.
19
19
#[ must_use]
20
20
#[ derive( Clone ) ]
21
- pub struct DiagnosticBuilder < ' a > {
22
- pub handler : & ' a Handler ,
21
+ pub struct DiagnosticBuilder < ' a > ( Box < DiagnosticBuilderInner < ' a > > ) ;
22
+
23
+ /// This is a large type, and often used as a return value, especially within
24
+ /// the frequently-used `PResult` type. In theory, return value optimization
25
+ /// (RVO) should avoid unnecessary copying. In practice, it does not (at the
26
+ /// time of writing). The split between `DiagnosticBuilder` and
27
+ /// `DiagnosticBuilderInner` exists to avoid many `memcpy` calls.
28
+ #[ must_use]
29
+ #[ derive( Clone ) ]
30
+ struct DiagnosticBuilderInner < ' a > {
31
+ handler : & ' a Handler ,
23
32
diagnostic : Diagnostic ,
24
33
allow_suggestions : bool ,
25
34
}
@@ -52,7 +61,7 @@ macro_rules! forward {
52
61
) => {
53
62
$( #[ $attrs] ) *
54
63
pub fn $n( & mut self , $( $name: $ty) ,* ) -> & mut Self {
55
- self . diagnostic. $n( $( $name) ,* ) ;
64
+ self . 0 . diagnostic. $n( $( $name) ,* ) ;
56
65
self
57
66
}
58
67
} ;
@@ -69,7 +78,7 @@ macro_rules! forward {
69
78
) => {
70
79
$( #[ $attrs] ) *
71
80
pub fn $n<S : Into <MultiSpan >>( & mut self , $( $name: $ty) ,* ) -> & mut Self {
72
- self . diagnostic. $n( $( $name) ,* ) ;
81
+ self . 0 . diagnostic. $n( $( $name) ,* ) ;
73
82
self
74
83
}
75
84
} ;
@@ -79,24 +88,28 @@ impl<'a> Deref for DiagnosticBuilder<'a> {
79
88
type Target = Diagnostic ;
80
89
81
90
fn deref ( & self ) -> & Diagnostic {
82
- & self . diagnostic
91
+ & self . 0 . diagnostic
83
92
}
84
93
}
85
94
86
95
impl < ' a > DerefMut for DiagnosticBuilder < ' a > {
87
96
fn deref_mut ( & mut self ) -> & mut Diagnostic {
88
- & mut self . diagnostic
97
+ & mut self . 0 . diagnostic
89
98
}
90
99
}
91
100
92
101
impl < ' a > DiagnosticBuilder < ' a > {
102
+ pub fn handler ( & self ) -> & ' a Handler {
103
+ self . 0 . handler
104
+ }
105
+
93
106
/// Emit the diagnostic.
94
107
pub fn emit ( & mut self ) {
95
108
if self . cancelled ( ) {
96
109
return ;
97
110
}
98
111
99
- self . handler . emit_db ( & self ) ;
112
+ self . 0 . handler . emit_db ( & self ) ;
100
113
self . cancel ( ) ;
101
114
}
102
115
@@ -115,8 +128,8 @@ impl<'a> DiagnosticBuilder<'a> {
115
128
/// Buffers the diagnostic for later emission, unless handler
116
129
/// has disabled such buffering.
117
130
pub fn buffer ( mut self , buffered_diagnostics : & mut Vec < Diagnostic > ) {
118
- if self . handler . flags . dont_buffer_diagnostics ||
119
- self . handler . flags . treat_err_as_bug . is_some ( )
131
+ if self . 0 . handler . flags . dont_buffer_diagnostics ||
132
+ self . 0 . handler . flags . treat_err_as_bug . is_some ( )
120
133
{
121
134
self . emit ( ) ;
122
135
return ;
@@ -126,7 +139,7 @@ impl<'a> DiagnosticBuilder<'a> {
126
139
// implements `Drop`.
127
140
let diagnostic;
128
141
unsafe {
129
- diagnostic = std:: ptr:: read ( & self . diagnostic ) ;
142
+ diagnostic = std:: ptr:: read ( & self . 0 . diagnostic ) ;
130
143
std:: mem:: forget ( self ) ;
131
144
} ;
132
145
// Logging here is useful to help track down where in logs an error was
@@ -144,7 +157,7 @@ impl<'a> DiagnosticBuilder<'a> {
144
157
span : Option < S > ,
145
158
) -> & mut Self {
146
159
let span = span. map ( |s| s. into ( ) ) . unwrap_or_else ( || MultiSpan :: new ( ) ) ;
147
- self . diagnostic . sub ( level, message, span, None ) ;
160
+ self . 0 . diagnostic . sub ( level, message, span, None ) ;
148
161
self
149
162
}
150
163
@@ -160,7 +173,7 @@ impl<'a> DiagnosticBuilder<'a> {
160
173
/// locally in whichever way makes the most sense.
161
174
pub fn delay_as_bug ( & mut self ) {
162
175
self . level = Level :: Bug ;
163
- self . handler . delay_as_bug ( self . diagnostic . clone ( ) ) ;
176
+ self . 0 . handler . delay_as_bug ( self . 0 . diagnostic . clone ( ) ) ;
164
177
self . cancel ( ) ;
165
178
}
166
179
@@ -171,7 +184,7 @@ impl<'a> DiagnosticBuilder<'a> {
171
184
/// then the snippet will just include that `Span`, which is
172
185
/// called the primary span.
173
186
pub fn span_label < T : Into < String > > ( & mut self , span : Span , label : T ) -> & mut Self {
174
- self . diagnostic . span_label ( span, label) ;
187
+ self . 0 . diagnostic . span_label ( span, label) ;
175
188
self
176
189
}
177
190
@@ -208,10 +221,10 @@ impl<'a> DiagnosticBuilder<'a> {
208
221
suggestion : Vec < ( Span , String ) > ,
209
222
applicability : Applicability ,
210
223
) -> & mut Self {
211
- if !self . allow_suggestions {
224
+ if !self . 0 . allow_suggestions {
212
225
return self
213
226
}
214
- self . diagnostic . multipart_suggestion (
227
+ self . 0 . diagnostic . multipart_suggestion (
215
228
msg,
216
229
suggestion,
217
230
applicability,
@@ -225,29 +238,28 @@ impl<'a> DiagnosticBuilder<'a> {
225
238
suggestion : Vec < ( Span , String ) > ,
226
239
applicability : Applicability ,
227
240
) -> & mut Self {
228
- if !self . allow_suggestions {
241
+ if !self . 0 . allow_suggestions {
229
242
return self
230
243
}
231
- self . diagnostic . tool_only_multipart_suggestion (
244
+ self . 0 . diagnostic . tool_only_multipart_suggestion (
232
245
msg,
233
246
suggestion,
234
247
applicability,
235
248
) ;
236
249
self
237
250
}
238
251
239
-
240
252
pub fn span_suggestion (
241
253
& mut self ,
242
254
sp : Span ,
243
255
msg : & str ,
244
256
suggestion : String ,
245
257
applicability : Applicability ,
246
258
) -> & mut Self {
247
- if !self . allow_suggestions {
259
+ if !self . 0 . allow_suggestions {
248
260
return self
249
261
}
250
- self . diagnostic . span_suggestion (
262
+ self . 0 . diagnostic . span_suggestion (
251
263
sp,
252
264
msg,
253
265
suggestion,
@@ -263,10 +275,10 @@ impl<'a> DiagnosticBuilder<'a> {
263
275
suggestions : impl Iterator < Item = String > ,
264
276
applicability : Applicability ,
265
277
) -> & mut Self {
266
- if !self . allow_suggestions {
278
+ if !self . 0 . allow_suggestions {
267
279
return self
268
280
}
269
- self . diagnostic . span_suggestions (
281
+ self . 0 . diagnostic . span_suggestions (
270
282
sp,
271
283
msg,
272
284
suggestions,
@@ -282,10 +294,10 @@ impl<'a> DiagnosticBuilder<'a> {
282
294
suggestion : String ,
283
295
applicability : Applicability ,
284
296
) -> & mut Self {
285
- if !self . allow_suggestions {
297
+ if !self . 0 . allow_suggestions {
286
298
return self
287
299
}
288
- self . diagnostic . span_suggestion_short (
300
+ self . 0 . diagnostic . span_suggestion_short (
289
301
sp,
290
302
msg,
291
303
suggestion,
@@ -301,10 +313,10 @@ impl<'a> DiagnosticBuilder<'a> {
301
313
suggestion : String ,
302
314
applicability : Applicability ,
303
315
) -> & mut Self {
304
- if !self . allow_suggestions {
316
+ if !self . 0 . allow_suggestions {
305
317
return self
306
318
}
307
- self . diagnostic . span_suggestion_hidden (
319
+ self . 0 . diagnostic . span_suggestion_hidden (
308
320
sp,
309
321
msg,
310
322
suggestion,
@@ -320,10 +332,10 @@ impl<'a> DiagnosticBuilder<'a> {
320
332
suggestion : String ,
321
333
applicability : Applicability ,
322
334
) -> & mut Self {
323
- if !self . allow_suggestions {
335
+ if !self . 0 . allow_suggestions {
324
336
return self
325
337
}
326
- self . diagnostic . tool_only_span_suggestion (
338
+ self . 0 . diagnostic . tool_only_span_suggestion (
327
339
sp,
328
340
msg,
329
341
suggestion,
@@ -336,7 +348,7 @@ impl<'a> DiagnosticBuilder<'a> {
336
348
forward ! ( pub fn code( & mut self , s: DiagnosticId ) -> & mut Self ) ;
337
349
338
350
pub fn allow_suggestions ( & mut self , allow : bool ) -> & mut Self {
339
- self . allow_suggestions = allow;
351
+ self . 0 . allow_suggestions = allow;
340
352
self
341
353
}
342
354
@@ -359,19 +371,18 @@ impl<'a> DiagnosticBuilder<'a> {
359
371
360
372
/// Creates a new `DiagnosticBuilder` with an already constructed
361
373
/// diagnostic.
362
- pub fn new_diagnostic ( handler : & ' a Handler , diagnostic : Diagnostic )
363
- -> DiagnosticBuilder < ' a > {
364
- DiagnosticBuilder {
374
+ pub fn new_diagnostic ( handler : & ' a Handler , diagnostic : Diagnostic ) -> DiagnosticBuilder < ' a > {
375
+ DiagnosticBuilder ( Box :: new ( DiagnosticBuilderInner {
365
376
handler,
366
377
diagnostic,
367
378
allow_suggestions : true ,
368
- }
379
+ } ) )
369
380
}
370
381
}
371
382
372
383
impl < ' a > Debug for DiagnosticBuilder < ' a > {
373
384
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
374
- self . diagnostic . fmt ( f)
385
+ self . 0 . diagnostic . fmt ( f)
375
386
}
376
387
}
377
388
@@ -381,7 +392,7 @@ impl<'a> Drop for DiagnosticBuilder<'a> {
381
392
fn drop ( & mut self ) {
382
393
if !panicking ( ) && !self . cancelled ( ) {
383
394
let mut db = DiagnosticBuilder :: new (
384
- self . handler ,
395
+ self . 0 . handler ,
385
396
Level :: Bug ,
386
397
"the following error was constructed but not emitted" ,
387
398
) ;
0 commit comments