@@ -126,9 +126,15 @@ impl<'tcx> ConstEvalErr<'tcx> {
126
126
}
127
127
}
128
128
129
- /// Sets the message passed in via `message` and adds span labels before handing control back
130
- /// to `emit` to do any final processing. It's the caller's responsibility to call emit(),
131
- /// stash(), etc. within the `emit` function to dispose of the diagnostic properly.
129
+ /// Create a diagnostic for this const eval error.
130
+ ///
131
+ /// Sets the message passed in via `message` and adds span labels with detailed error
132
+ /// information before handing control back to `emit` to do any final processing.
133
+ /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit`
134
+ /// function to dispose of the diagnostic properly.
135
+ ///
136
+ /// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
137
+ /// (Except that for some errors, we ignore all that -- see `must_error` below.)
132
138
fn struct_generic (
133
139
& self ,
134
140
tcx : TyCtxtAt < ' tcx > ,
@@ -141,6 +147,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
141
147
return Err ( ErrorHandled :: TooGeneric ) ;
142
148
}
143
149
err_inval ! ( TypeckError ) => return Err ( ErrorHandled :: Reported ) ,
150
+ // We must *always* hard error on these, even if the caller wants just a lint.
144
151
err_inval ! ( Layout ( LayoutError :: SizeOverflow ( _) ) ) => true ,
145
152
_ => false ,
146
153
} ;
@@ -155,10 +162,11 @@ impl<'tcx> ConstEvalErr<'tcx> {
155
162
err => err. to_string ( ) ,
156
163
} ;
157
164
158
- let add_span_labels = |err : & mut DiagnosticBuilder < ' _ > | {
159
- if !must_error {
160
- err. span_label ( self . span , err_msg . clone ( ) ) ;
165
+ let finish = |mut err : DiagnosticBuilder < ' _ > , span_msg : Option < String > | {
166
+ if let Some ( span_msg ) = span_msg {
167
+ err. span_label ( self . span , span_msg ) ;
161
168
}
169
+ // Add spans for the stacktrace.
162
170
// Skip the last, which is just the environment of the constant. The stacktrace
163
171
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
164
172
// on constant values.
@@ -167,35 +175,36 @@ impl<'tcx> ConstEvalErr<'tcx> {
167
175
err. span_label ( frame_info. call_site , frame_info. to_string ( ) ) ;
168
176
}
169
177
}
178
+ // Let the caller finish the job.
179
+ emit ( err)
170
180
} ;
171
181
172
- if let ( Some ( lint_root) , false ) = ( lint_root, must_error) {
173
- let hir_id = self
174
- . stacktrace
175
- . iter ( )
176
- . rev ( )
177
- . filter_map ( |frame| frame. lint_root )
178
- . next ( )
179
- . unwrap_or ( lint_root) ;
180
- tcx. struct_span_lint_hir (
181
- rustc_session:: lint:: builtin:: CONST_ERR ,
182
- hir_id,
183
- tcx. span ,
184
- |lint| {
185
- let mut err = lint. build ( message) ;
186
- add_span_labels ( & mut err) ;
187
- emit ( err) ;
188
- } ,
189
- ) ;
182
+ if must_error {
183
+ // The `message` makes little sense here, this is a more serious error than the
184
+ // caller thinks anyway.
185
+ finish ( struct_error ( tcx, & err_msg) , None ) ;
190
186
} else {
191
- let mut err = if must_error {
192
- struct_error ( tcx, & err_msg)
187
+ // Regular case.
188
+ if let Some ( lint_root) = lint_root {
189
+ // Report as lint.
190
+ let hir_id = self
191
+ . stacktrace
192
+ . iter ( )
193
+ . rev ( )
194
+ . filter_map ( |frame| frame. lint_root )
195
+ . next ( )
196
+ . unwrap_or ( lint_root) ;
197
+ tcx. struct_span_lint_hir (
198
+ rustc_session:: lint:: builtin:: CONST_ERR ,
199
+ hir_id,
200
+ tcx. span ,
201
+ |lint| finish ( lint. build ( message) , Some ( err_msg) ) ,
202
+ ) ;
193
203
} else {
194
- struct_error ( tcx, message)
195
- } ;
196
- add_span_labels ( & mut err) ;
197
- emit ( err) ;
198
- } ;
204
+ // Report as hard error.
205
+ finish ( struct_error ( tcx, message) , Some ( err_msg) ) ;
206
+ }
207
+ }
199
208
Ok ( ( ) )
200
209
}
201
210
}
0 commit comments