@@ -86,6 +86,59 @@ impl<'tcx> ConstEvalErr<'tcx> {
8686 self . report_decorated ( tcx, message, |_| { } )
8787 }
8888
89+ #[ instrument( level = "trace" , skip( self , decorate) ) ]
90+ pub ( super ) fn decorate ( & self , err : & mut Diagnostic , decorate : impl FnOnce ( & mut Diagnostic ) ) {
91+ trace ! ( "reporting const eval failure at {:?}" , self . span) ;
92+ // Add some more context for select error types.
93+ match self . error {
94+ InterpError :: Unsupported (
95+ UnsupportedOpInfo :: ReadPointerAsBytes
96+ | UnsupportedOpInfo :: PartialPointerOverwrite ( _)
97+ | UnsupportedOpInfo :: PartialPointerCopy ( _) ,
98+ ) => {
99+ err. help ( "this code performed an operation that depends on the underlying bytes representing a pointer" ) ;
100+ err. help ( "the absolute address of a pointer is not known at compile-time, so such operations are not supported" ) ;
101+ }
102+ _ => { }
103+ }
104+ // Add spans for the stacktrace. Don't print a single-line backtrace though.
105+ if self . stacktrace . len ( ) > 1 {
106+ // Helper closure to print duplicated lines.
107+ let mut flush_last_line = |last_frame, times| {
108+ if let Some ( ( line, span) ) = last_frame {
109+ err. span_note ( span, & line) ;
110+ // Don't print [... additional calls ...] if the number of lines is small
111+ if times < 3 {
112+ for _ in 0 ..times {
113+ err. span_note ( span, & line) ;
114+ }
115+ } else {
116+ err. span_note (
117+ span,
118+ format ! ( "[... {} additional calls {} ...]" , times, & line) ,
119+ ) ;
120+ }
121+ }
122+ } ;
123+
124+ let mut last_frame = None ;
125+ let mut times = 0 ;
126+ for frame_info in & self . stacktrace {
127+ let frame = ( frame_info. to_string ( ) , frame_info. span ) ;
128+ if last_frame. as_ref ( ) == Some ( & frame) {
129+ times += 1 ;
130+ } else {
131+ flush_last_line ( last_frame, times) ;
132+ last_frame = Some ( frame) ;
133+ times = 0 ;
134+ }
135+ }
136+ flush_last_line ( last_frame, times) ;
137+ }
138+ // Let the caller attach any additional information it wants.
139+ decorate ( err) ;
140+ }
141+
89142 /// Create a diagnostic for this const eval error.
90143 ///
91144 /// Sets the message passed in via `message` and adds span labels with detailed error
@@ -101,88 +154,30 @@ impl<'tcx> ConstEvalErr<'tcx> {
101154 message : & str ,
102155 decorate : impl FnOnce ( & mut Diagnostic ) ,
103156 ) -> ErrorHandled {
104- let finish = |err : & mut Diagnostic , span_msg : Option < String > | {
105- trace ! ( "reporting const eval failure at {:?}" , self . span) ;
106- if let Some ( span_msg) = span_msg {
107- err. span_label ( self . span , span_msg) ;
108- }
109- // Add some more context for select error types.
110- match self . error {
111- InterpError :: Unsupported (
112- UnsupportedOpInfo :: ReadPointerAsBytes
113- | UnsupportedOpInfo :: PartialPointerOverwrite ( _)
114- | UnsupportedOpInfo :: PartialPointerCopy ( _) ,
115- ) => {
116- err. help ( "this code performed an operation that depends on the underlying bytes representing a pointer" ) ;
117- err. help ( "the absolute address of a pointer is not known at compile-time, so such operations are not supported" ) ;
118- }
119- _ => { }
120- }
121- // Add spans for the stacktrace. Don't print a single-line backtrace though.
122- if self . stacktrace . len ( ) > 1 {
123- // Helper closure to print duplicated lines.
124- let mut flush_last_line = |last_frame, times| {
125- if let Some ( ( line, span) ) = last_frame {
126- err. span_note ( span, & line) ;
127- // Don't print [... additional calls ...] if the number of lines is small
128- if times < 3 {
129- for _ in 0 ..times {
130- err. span_note ( span, & line) ;
131- }
132- } else {
133- err. span_note (
134- span,
135- format ! ( "[... {} additional calls {} ...]" , times, & line) ,
136- ) ;
137- }
138- }
139- } ;
140-
141- let mut last_frame = None ;
142- let mut times = 0 ;
143- for frame_info in & self . stacktrace {
144- let frame = ( frame_info. to_string ( ) , frame_info. span ) ;
145- if last_frame. as_ref ( ) == Some ( & frame) {
146- times += 1 ;
147- } else {
148- flush_last_line ( last_frame, times) ;
149- last_frame = Some ( frame) ;
150- times = 0 ;
151- }
152- }
153- flush_last_line ( last_frame, times) ;
154- }
155- // Let the caller attach any additional information it wants.
156- decorate ( err) ;
157- } ;
158-
159157 debug ! ( "self.error: {:?}" , self . error) ;
160158 // Special handling for certain errors
161159 match & self . error {
162160 // Don't emit a new diagnostic for these errors
163161 err_inval ! ( Layout ( LayoutError :: Unknown ( _) ) ) | err_inval ! ( TooGeneric ) => {
164- return ErrorHandled :: TooGeneric ;
165- }
166- err_inval ! ( AlreadyReported ( error_reported) ) => {
167- return ErrorHandled :: Reported ( * error_reported) ;
162+ ErrorHandled :: TooGeneric
168163 }
164+ err_inval ! ( AlreadyReported ( error_reported) ) => ErrorHandled :: Reported ( * error_reported) ,
169165 err_inval ! ( Layout ( LayoutError :: SizeOverflow ( _) ) ) => {
170166 // We must *always* hard error on these, even if the caller wants just a lint.
171167 // The `message` makes little sense here, this is a more serious error than the
172168 // caller thinks anyway.
173169 // See <https://github.com/rust-lang/rust/pull/63152>.
174170 let mut err = struct_error ( tcx, & self . error . to_string ( ) ) ;
175- finish ( & mut err, None ) ;
176- return ErrorHandled :: Reported ( err. emit ( ) ) ;
171+ self . decorate ( & mut err, decorate ) ;
172+ ErrorHandled :: Reported ( err. emit ( ) )
177173 }
178- _ => { }
179- } ;
180-
181- let err_msg = self . error . to_string ( ) ;
182-
183- // Report as hard error.
184- let mut err = struct_error ( tcx, message) ;
185- finish ( & mut err, Some ( err_msg) ) ;
186- ErrorHandled :: Reported ( err. emit ( ) )
174+ _ => {
175+ // Report as hard error.
176+ let mut err = struct_error ( tcx, message) ;
177+ err. span_label ( self . span , self . error . to_string ( ) ) ;
178+ self . decorate ( & mut err, decorate) ;
179+ ErrorHandled :: Reported ( err. emit ( ) )
180+ }
181+ }
187182 }
188183}
0 commit comments