@@ -18,8 +18,17 @@ use log::debug;
1818/// extending `HandlerFlags`, accessed via `self.handler.flags`.
1919#[ must_use]
2020#[ 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 ,
2332 diagnostic : Diagnostic ,
2433 allow_suggestions : bool ,
2534}
@@ -52,7 +61,7 @@ macro_rules! forward {
5261 ) => {
5362 $( #[ $attrs] ) *
5463 pub fn $n( & mut self , $( $name: $ty) ,* ) -> & mut Self {
55- self . diagnostic. $n( $( $name) ,* ) ;
64+ self . 0 . diagnostic. $n( $( $name) ,* ) ;
5665 self
5766 }
5867 } ;
@@ -69,7 +78,7 @@ macro_rules! forward {
6978 ) => {
7079 $( #[ $attrs] ) *
7180 pub fn $n<S : Into <MultiSpan >>( & mut self , $( $name: $ty) ,* ) -> & mut Self {
72- self . diagnostic. $n( $( $name) ,* ) ;
81+ self . 0 . diagnostic. $n( $( $name) ,* ) ;
7382 self
7483 }
7584 } ;
@@ -79,24 +88,28 @@ impl<'a> Deref for DiagnosticBuilder<'a> {
7988 type Target = Diagnostic ;
8089
8190 fn deref ( & self ) -> & Diagnostic {
82- & self . diagnostic
91+ & self . 0 . diagnostic
8392 }
8493}
8594
8695impl < ' a > DerefMut for DiagnosticBuilder < ' a > {
8796 fn deref_mut ( & mut self ) -> & mut Diagnostic {
88- & mut self . diagnostic
97+ & mut self . 0 . diagnostic
8998 }
9099}
91100
92101impl < ' a > DiagnosticBuilder < ' a > {
102+ pub fn handler ( & self ) -> & ' a Handler {
103+ self . 0 . handler
104+ }
105+
93106 /// Emit the diagnostic.
94107 pub fn emit ( & mut self ) {
95108 if self . cancelled ( ) {
96109 return ;
97110 }
98111
99- self . handler . emit_db ( & self ) ;
112+ self . 0 . handler . emit_db ( & self ) ;
100113 self . cancel ( ) ;
101114 }
102115
@@ -115,8 +128,8 @@ impl<'a> DiagnosticBuilder<'a> {
115128 /// Buffers the diagnostic for later emission, unless handler
116129 /// has disabled such buffering.
117130 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 ( )
120133 {
121134 self . emit ( ) ;
122135 return ;
@@ -126,7 +139,7 @@ impl<'a> DiagnosticBuilder<'a> {
126139 // implements `Drop`.
127140 let diagnostic;
128141 unsafe {
129- diagnostic = std:: ptr:: read ( & self . diagnostic ) ;
142+ diagnostic = std:: ptr:: read ( & self . 0 . diagnostic ) ;
130143 std:: mem:: forget ( self ) ;
131144 } ;
132145 // Logging here is useful to help track down where in logs an error was
@@ -144,7 +157,7 @@ impl<'a> DiagnosticBuilder<'a> {
144157 span : Option < S > ,
145158 ) -> & mut Self {
146159 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 ) ;
148161 self
149162 }
150163
@@ -160,7 +173,7 @@ impl<'a> DiagnosticBuilder<'a> {
160173 /// locally in whichever way makes the most sense.
161174 pub fn delay_as_bug ( & mut self ) {
162175 self . level = Level :: Bug ;
163- self . handler . delay_as_bug ( self . diagnostic . clone ( ) ) ;
176+ self . 0 . handler . delay_as_bug ( self . 0 . diagnostic . clone ( ) ) ;
164177 self . cancel ( ) ;
165178 }
166179
@@ -171,7 +184,7 @@ impl<'a> DiagnosticBuilder<'a> {
171184 /// then the snippet will just include that `Span`, which is
172185 /// called the primary span.
173186 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) ;
175188 self
176189 }
177190
@@ -208,10 +221,10 @@ impl<'a> DiagnosticBuilder<'a> {
208221 suggestion : Vec < ( Span , String ) > ,
209222 applicability : Applicability ,
210223 ) -> & mut Self {
211- if !self . allow_suggestions {
224+ if !self . 0 . allow_suggestions {
212225 return self
213226 }
214- self . diagnostic . multipart_suggestion (
227+ self . 0 . diagnostic . multipart_suggestion (
215228 msg,
216229 suggestion,
217230 applicability,
@@ -225,29 +238,28 @@ impl<'a> DiagnosticBuilder<'a> {
225238 suggestion : Vec < ( Span , String ) > ,
226239 applicability : Applicability ,
227240 ) -> & mut Self {
228- if !self . allow_suggestions {
241+ if !self . 0 . allow_suggestions {
229242 return self
230243 }
231- self . diagnostic . tool_only_multipart_suggestion (
244+ self . 0 . diagnostic . tool_only_multipart_suggestion (
232245 msg,
233246 suggestion,
234247 applicability,
235248 ) ;
236249 self
237250 }
238251
239-
240252 pub fn span_suggestion (
241253 & mut self ,
242254 sp : Span ,
243255 msg : & str ,
244256 suggestion : String ,
245257 applicability : Applicability ,
246258 ) -> & mut Self {
247- if !self . allow_suggestions {
259+ if !self . 0 . allow_suggestions {
248260 return self
249261 }
250- self . diagnostic . span_suggestion (
262+ self . 0 . diagnostic . span_suggestion (
251263 sp,
252264 msg,
253265 suggestion,
@@ -263,10 +275,10 @@ impl<'a> DiagnosticBuilder<'a> {
263275 suggestions : impl Iterator < Item = String > ,
264276 applicability : Applicability ,
265277 ) -> & mut Self {
266- if !self . allow_suggestions {
278+ if !self . 0 . allow_suggestions {
267279 return self
268280 }
269- self . diagnostic . span_suggestions (
281+ self . 0 . diagnostic . span_suggestions (
270282 sp,
271283 msg,
272284 suggestions,
@@ -282,10 +294,10 @@ impl<'a> DiagnosticBuilder<'a> {
282294 suggestion : String ,
283295 applicability : Applicability ,
284296 ) -> & mut Self {
285- if !self . allow_suggestions {
297+ if !self . 0 . allow_suggestions {
286298 return self
287299 }
288- self . diagnostic . span_suggestion_short (
300+ self . 0 . diagnostic . span_suggestion_short (
289301 sp,
290302 msg,
291303 suggestion,
@@ -301,10 +313,10 @@ impl<'a> DiagnosticBuilder<'a> {
301313 suggestion : String ,
302314 applicability : Applicability ,
303315 ) -> & mut Self {
304- if !self . allow_suggestions {
316+ if !self . 0 . allow_suggestions {
305317 return self
306318 }
307- self . diagnostic . span_suggestion_hidden (
319+ self . 0 . diagnostic . span_suggestion_hidden (
308320 sp,
309321 msg,
310322 suggestion,
@@ -320,10 +332,10 @@ impl<'a> DiagnosticBuilder<'a> {
320332 suggestion : String ,
321333 applicability : Applicability ,
322334 ) -> & mut Self {
323- if !self . allow_suggestions {
335+ if !self . 0 . allow_suggestions {
324336 return self
325337 }
326- self . diagnostic . tool_only_span_suggestion (
338+ self . 0 . diagnostic . tool_only_span_suggestion (
327339 sp,
328340 msg,
329341 suggestion,
@@ -336,7 +348,7 @@ impl<'a> DiagnosticBuilder<'a> {
336348 forward ! ( pub fn code( & mut self , s: DiagnosticId ) -> & mut Self ) ;
337349
338350 pub fn allow_suggestions ( & mut self , allow : bool ) -> & mut Self {
339- self . allow_suggestions = allow;
351+ self . 0 . allow_suggestions = allow;
340352 self
341353 }
342354
@@ -359,19 +371,18 @@ impl<'a> DiagnosticBuilder<'a> {
359371
360372 /// Creates a new `DiagnosticBuilder` with an already constructed
361373 /// 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 {
365376 handler,
366377 diagnostic,
367378 allow_suggestions : true ,
368- }
379+ } ) )
369380 }
370381}
371382
372383impl < ' a > Debug for DiagnosticBuilder < ' a > {
373384 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
374- self . diagnostic . fmt ( f)
385+ self . 0 . diagnostic . fmt ( f)
375386 }
376387}
377388
@@ -381,7 +392,7 @@ impl<'a> Drop for DiagnosticBuilder<'a> {
381392 fn drop ( & mut self ) {
382393 if !panicking ( ) && !self . cancelled ( ) {
383394 let mut db = DiagnosticBuilder :: new (
384- self . handler ,
395+ self . 0 . handler ,
385396 Level :: Bug ,
386397 "the following error was constructed but not emitted" ,
387398 ) ;
0 commit comments