@@ -5,12 +5,8 @@ use std::error::Error;
5
5
use std:: fmt;
6
6
use std:: hash:: Hash ;
7
7
8
- use crate :: interpret:: eval_nullary_intrinsic;
9
- use crate :: interpret:: eval_nullary_intrinsic;
10
- use rustc:: hir:: def:: DefKind ;
11
8
use rustc:: mir;
12
- use rustc:: mir:: interpret:: { ConstEvalErr , ErrorHandled , ScalarMaybeUndef } ;
13
- use rustc:: traits:: Reveal ;
9
+ use rustc:: mir:: interpret:: ScalarMaybeUndef ;
14
10
use rustc:: ty:: layout:: { self , LayoutOf , VariantIdx } ;
15
11
use rustc:: ty:: { self , subst:: Subst , TyCtxt } ;
16
12
@@ -21,15 +17,14 @@ use syntax::{
21
17
22
18
use crate :: interpret:: {
23
19
intern_const_alloc_recursive, Allocation , ConstValue , GlobalId , ImmTy , Immediate , InterpCx ,
24
- InterpErrorInfo , InterpResult , MPlaceTy , Machine , MemoryKind , OpTy , RawConst , RefTracking ,
25
- Scalar , StackPopCleanup ,
20
+ InterpResult , MPlaceTy , MemoryKind , OpTy , Scalar , StackPopCleanup ,
26
21
} ;
27
22
28
23
mod error;
29
- mod machine ;
24
+ mod query ;
30
25
31
26
pub use error:: * ;
32
- pub use machine :: * ;
27
+ pub use query :: * ;
33
28
34
29
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
35
30
/// `simd_shuffle` and const patterns in match arms.
@@ -225,220 +220,3 @@ pub fn const_variant_index<'tcx>(
225
220
let op = ecx. eval_const_to_op ( val, None ) . unwrap ( ) ;
226
221
ecx. read_discriminant ( op) . unwrap ( ) . 1
227
222
}
228
-
229
- /// Turn an interpreter error into something to report to the user.
230
- /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
231
- /// Should be called only if the error is actually going to to be reported!
232
- pub fn error_to_const_error < ' mir , ' tcx , M : Machine < ' mir , ' tcx > > (
233
- ecx : & InterpCx < ' mir , ' tcx , M > ,
234
- mut error : InterpErrorInfo < ' tcx > ,
235
- ) -> ConstEvalErr < ' tcx > {
236
- error. print_backtrace ( ) ;
237
- let stacktrace = ecx. generate_stacktrace ( None ) ;
238
- ConstEvalErr { error : error. kind , stacktrace, span : ecx. tcx . span }
239
- }
240
-
241
- pub fn note_on_undefined_behavior_error ( ) -> & ' static str {
242
- "The rules on what exactly is undefined behavior aren't clear, \
243
- so this check might be overzealous. Please open an issue on the rustc \
244
- repository if you believe it should not be considered undefined behavior."
245
- }
246
-
247
- fn validate_and_turn_into_const < ' tcx > (
248
- tcx : TyCtxt < ' tcx > ,
249
- constant : RawConst < ' tcx > ,
250
- key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
251
- ) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
252
- let cid = key. value ;
253
- let def_id = cid. instance . def . def_id ( ) ;
254
- let is_static = tcx. is_static ( def_id) ;
255
- let ecx = mk_eval_cx ( tcx, tcx. def_span ( key. value . instance . def_id ( ) ) , key. param_env , is_static) ;
256
- let val = ( || {
257
- let mplace = ecx. raw_const_to_mplace ( constant) ?;
258
- let mut ref_tracking = RefTracking :: new ( mplace) ;
259
- while let Some ( ( mplace, path) ) = ref_tracking. todo . pop ( ) {
260
- ecx. validate_operand ( mplace. into ( ) , path, Some ( & mut ref_tracking) ) ?;
261
- }
262
- // Now that we validated, turn this into a proper constant.
263
- // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
264
- // whether they become immediates.
265
- if is_static || cid. promoted . is_some ( ) {
266
- let ptr = mplace. ptr . to_ptr ( ) ?;
267
- Ok ( tcx. mk_const ( ty:: Const {
268
- val : ty:: ConstKind :: Value ( ConstValue :: ByRef {
269
- alloc : ecx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ,
270
- offset : ptr. offset ,
271
- } ) ,
272
- ty : mplace. layout . ty ,
273
- } ) )
274
- } else {
275
- Ok ( op_to_const ( & ecx, mplace. into ( ) ) )
276
- }
277
- } ) ( ) ;
278
-
279
- val. map_err ( |error| {
280
- let err = error_to_const_error ( & ecx, error) ;
281
- match err. struct_error ( ecx. tcx , "it is undefined behavior to use this value" ) {
282
- Ok ( mut diag) => {
283
- diag. note ( note_on_undefined_behavior_error ( ) ) ;
284
- diag. emit ( ) ;
285
- ErrorHandled :: Reported
286
- }
287
- Err ( err) => err,
288
- }
289
- } )
290
- }
291
-
292
- pub fn const_eval_validated_provider < ' tcx > (
293
- tcx : TyCtxt < ' tcx > ,
294
- key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
295
- ) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
296
- // see comment in const_eval_raw_provider for what we're doing here
297
- if key. param_env . reveal == Reveal :: All {
298
- let mut key = key. clone ( ) ;
299
- key. param_env . reveal = Reveal :: UserFacing ;
300
- match tcx. const_eval_validated ( key) {
301
- // try again with reveal all as requested
302
- Err ( ErrorHandled :: TooGeneric ) => {
303
- // Promoteds should never be "too generic" when getting evaluated.
304
- // They either don't get evaluated, or we are in a monomorphic context
305
- assert ! ( key. value. promoted. is_none( ) ) ;
306
- }
307
- // dedupliate calls
308
- other => return other,
309
- }
310
- }
311
-
312
- // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
313
- // Catch such calls and evaluate them instead of trying to load a constant's MIR.
314
- if let ty:: InstanceDef :: Intrinsic ( def_id) = key. value . instance . def {
315
- let ty = key. value . instance . ty ( tcx) ;
316
- let substs = match ty. kind {
317
- ty:: FnDef ( _, substs) => substs,
318
- _ => bug ! ( "intrinsic with type {:?}" , ty) ,
319
- } ;
320
- return eval_nullary_intrinsic ( tcx, key. param_env , def_id, substs) . map_err ( |error| {
321
- let span = tcx. def_span ( def_id) ;
322
- let error = ConstEvalErr { error : error. kind , stacktrace : vec ! [ ] , span } ;
323
- error. report_as_error ( tcx. at ( span) , "could not evaluate nullary intrinsic" )
324
- } ) ;
325
- }
326
-
327
- tcx. const_eval_raw ( key) . and_then ( |val| validate_and_turn_into_const ( tcx, val, key) )
328
- }
329
-
330
- pub fn const_eval_raw_provider < ' tcx > (
331
- tcx : TyCtxt < ' tcx > ,
332
- key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
333
- ) -> :: rustc:: mir:: interpret:: ConstEvalRawResult < ' tcx > {
334
- // Because the constant is computed twice (once per value of `Reveal`), we are at risk of
335
- // reporting the same error twice here. To resolve this, we check whether we can evaluate the
336
- // constant in the more restrictive `Reveal::UserFacing`, which most likely already was
337
- // computed. For a large percentage of constants that will already have succeeded. Only
338
- // associated constants of generic functions will fail due to not enough monomorphization
339
- // information being available.
340
-
341
- // In case we fail in the `UserFacing` variant, we just do the real computation.
342
- if key. param_env . reveal == Reveal :: All {
343
- let mut key = key. clone ( ) ;
344
- key. param_env . reveal = Reveal :: UserFacing ;
345
- match tcx. const_eval_raw ( key) {
346
- // try again with reveal all as requested
347
- Err ( ErrorHandled :: TooGeneric ) => { }
348
- // dedupliate calls
349
- other => return other,
350
- }
351
- }
352
- if cfg ! ( debug_assertions) {
353
- // Make sure we format the instance even if we do not print it.
354
- // This serves as a regression test against an ICE on printing.
355
- // The next two lines concatenated contain some discussion:
356
- // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
357
- // subject/anon_const_instance_printing/near/135980032
358
- let instance = key. value . instance . to_string ( ) ;
359
- trace ! ( "const eval: {:?} ({})" , key, instance) ;
360
- }
361
-
362
- let cid = key. value ;
363
- let def_id = cid. instance . def . def_id ( ) ;
364
-
365
- if def_id. is_local ( ) && tcx. typeck_tables_of ( def_id) . tainted_by_errors {
366
- return Err ( ErrorHandled :: Reported ) ;
367
- }
368
-
369
- let is_static = tcx. is_static ( def_id) ;
370
-
371
- let span = tcx. def_span ( cid. instance . def_id ( ) ) ;
372
- let mut ecx = InterpCx :: new (
373
- tcx. at ( span) ,
374
- key. param_env ,
375
- CompileTimeInterpreter :: new ( ) ,
376
- MemoryExtra { can_access_statics : is_static } ,
377
- ) ;
378
-
379
- let res = ecx. load_mir ( cid. instance . def , cid. promoted ) ;
380
- res. and_then ( |body| eval_body_using_ecx ( & mut ecx, cid, * body) )
381
- . and_then ( |place| {
382
- Ok ( RawConst { alloc_id : place. ptr . assert_ptr ( ) . alloc_id , ty : place. layout . ty } )
383
- } )
384
- . map_err ( |error| {
385
- let err = error_to_const_error ( & ecx, error) ;
386
- // errors in statics are always emitted as fatal errors
387
- if is_static {
388
- // Ensure that if the above error was either `TooGeneric` or `Reported`
389
- // an error must be reported.
390
- let v = err. report_as_error ( ecx. tcx , "could not evaluate static initializer" ) ;
391
- tcx. sess . delay_span_bug (
392
- err. span ,
393
- & format ! ( "static eval failure did not emit an error: {:#?}" , v) ,
394
- ) ;
395
- v
396
- } else if def_id. is_local ( ) {
397
- // constant defined in this crate, we can figure out a lint level!
398
- match tcx. def_kind ( def_id) {
399
- // constants never produce a hard error at the definition site. Anything else is
400
- // a backwards compatibility hazard (and will break old versions of winapi for sure)
401
- //
402
- // note that validation may still cause a hard error on this very same constant,
403
- // because any code that existed before validation could not have failed validation
404
- // thus preventing such a hard error from being a backwards compatibility hazard
405
- Some ( DefKind :: Const ) | Some ( DefKind :: AssocConst ) => {
406
- let hir_id = tcx. hir ( ) . as_local_hir_id ( def_id) . unwrap ( ) ;
407
- err. report_as_lint (
408
- tcx. at ( tcx. def_span ( def_id) ) ,
409
- "any use of this value will cause an error" ,
410
- hir_id,
411
- Some ( err. span ) ,
412
- )
413
- }
414
- // promoting runtime code is only allowed to error if it references broken constants
415
- // any other kind of error will be reported to the user as a deny-by-default lint
416
- _ => {
417
- if let Some ( p) = cid. promoted {
418
- let span = tcx. promoted_mir ( def_id) [ p] . span ;
419
- if let err_inval ! ( ReferencedConstant ) = err. error {
420
- err. report_as_error (
421
- tcx. at ( span) ,
422
- "evaluation of constant expression failed" ,
423
- )
424
- } else {
425
- err. report_as_lint (
426
- tcx. at ( span) ,
427
- "reaching this expression at runtime will panic or abort" ,
428
- tcx. hir ( ) . as_local_hir_id ( def_id) . unwrap ( ) ,
429
- Some ( err. span ) ,
430
- )
431
- }
432
- // anything else (array lengths, enum initializers, constant patterns) are reported
433
- // as hard errors
434
- } else {
435
- err. report_as_error ( ecx. tcx , "evaluation of constant value failed" )
436
- }
437
- }
438
- }
439
- } else {
440
- // use of broken constant from other crate
441
- err. report_as_error ( ecx. tcx , "could not evaluate constant" )
442
- }
443
- } )
444
- }
0 commit comments