@@ -6,6 +6,7 @@ use std::cell::Cell;
6
6
7
7
use rustc:: hir:: def:: DefKind ;
8
8
use rustc:: hir:: def_id:: DefId ;
9
+ use rustc:: hir:: HirId ;
9
10
use rustc:: mir:: interpret:: { InterpResult , PanicInfo , Scalar } ;
10
11
use rustc:: mir:: visit:: {
11
12
MutVisitor , MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor ,
@@ -33,7 +34,6 @@ use crate::interpret::{
33
34
ScalarMaybeUndef , StackPopCleanup ,
34
35
} ;
35
36
use crate :: rustc:: ty:: subst:: Subst ;
36
- use crate :: rustc:: ty:: TypeFoldable ;
37
37
use crate :: transform:: { MirPass , MirSource } ;
38
38
39
39
/// The maximum number of bytes that we'll allocate space for a return value.
@@ -261,6 +261,9 @@ struct ConstPropagator<'mir, 'tcx> {
261
261
source_scopes : IndexVec < SourceScope , SourceScopeData > ,
262
262
local_decls : IndexVec < Local , LocalDecl < ' tcx > > ,
263
263
ret : Option < OpTy < ' tcx , ( ) > > ,
264
+ // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
265
+ // the last known `SourceInfo` here and just keep revisiting it.
266
+ source_info : Option < SourceInfo > ,
264
267
}
265
268
266
269
impl < ' mir , ' tcx > LayoutOf for ConstPropagator < ' mir , ' tcx > {
@@ -339,6 +342,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
339
342
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
340
343
local_decls : body. local_decls . clone ( ) ,
341
344
ret : ret. map ( Into :: into) ,
345
+ source_info : None ,
342
346
}
343
347
}
344
348
@@ -360,6 +364,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
360
364
LocalState { value : LocalValue :: Uninitialized , layout : Cell :: new ( None ) } ;
361
365
}
362
366
367
+ fn lint_root ( & self , source_info : SourceInfo ) -> Option < HirId > {
368
+ match & self . source_scopes [ source_info. scope ] . local_data {
369
+ ClearCrossCrate :: Set ( data) => Some ( data. lint_root ) ,
370
+ ClearCrossCrate :: Clear => None ,
371
+ }
372
+ }
373
+
363
374
fn use_ecx < F , T > ( & mut self , source_info : SourceInfo , f : F ) -> Option < T >
364
375
where
365
376
F : FnOnce ( & mut Self ) -> InterpResult < ' tcx , T > ,
@@ -368,10 +379,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
368
379
// FIXME(eddyb) move this to the `Panic(_)` error case, so that
369
380
// `f(self)` is always called, and that the only difference when the
370
381
// scope's `local_data` is missing, is that the lint isn't emitted.
371
- let lint_root = match & self . source_scopes [ source_info. scope ] . local_data {
372
- ClearCrossCrate :: Set ( data) => data. lint_root ,
373
- ClearCrossCrate :: Clear => return None ,
374
- } ;
382
+ let lint_root = self . lint_root ( source_info) ?;
375
383
let r = match f ( self ) {
376
384
Ok ( val) => Some ( val) ,
377
385
Err ( error) => {
@@ -417,19 +425,31 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
417
425
r
418
426
}
419
427
420
- fn eval_constant ( & mut self , c : & Constant < ' tcx > ) -> Option < Const < ' tcx > > {
421
- // `eval_const_to_op` uses `Instance::resolve` which still has a bug (#66901) in the
422
- // presence of trait items with a default body. So we just bail out if we aren't 100%
423
- // monomorphic.
424
- if c. literal . needs_subst ( ) {
425
- return None ;
426
- }
428
+ fn eval_constant (
429
+ & mut self ,
430
+ c : & Constant < ' tcx > ,
431
+ source_info : SourceInfo ,
432
+ ) -> Option < Const < ' tcx > > {
427
433
self . ecx . tcx . span = c. span ;
428
434
match self . ecx . eval_const_to_op ( c. literal , None ) {
429
435
Ok ( op) => Some ( op) ,
430
436
Err ( error) => {
431
437
let err = error_to_const_error ( & self . ecx , error) ;
432
- err. report_as_error ( self . ecx . tcx , "erroneous constant used" ) ;
438
+ match self . lint_root ( source_info) {
439
+ Some ( lint_root) if c. literal . needs_subst ( ) => {
440
+ // Out of backwards compatibility we cannot report hard errors in unused
441
+ // generic functions using associated constants of the generic parameters.
442
+ err. report_as_lint (
443
+ self . ecx . tcx ,
444
+ "erroneous constant used" ,
445
+ lint_root,
446
+ Some ( c. span ) ,
447
+ ) ;
448
+ }
449
+ _ => {
450
+ err. report_as_error ( self . ecx . tcx , "erroneous constant used" ) ;
451
+ }
452
+ }
433
453
None
434
454
}
435
455
}
@@ -442,7 +462,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
442
462
443
463
fn eval_operand ( & mut self , op : & Operand < ' tcx > , source_info : SourceInfo ) -> Option < Const < ' tcx > > {
444
464
match * op {
445
- Operand :: Constant ( ref c) => self . eval_constant ( c) ,
465
+ Operand :: Constant ( ref c) => self . eval_constant ( c, source_info ) ,
446
466
Operand :: Move ( ref place) | Operand :: Copy ( ref place) => {
447
467
self . eval_place ( place, source_info)
448
468
}
@@ -509,10 +529,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
509
529
let right_size = r. layout . size ;
510
530
let r_bits = r. to_scalar ( ) . and_then ( |r| r. to_bits ( right_size) ) ;
511
531
if r_bits. map_or ( false , |b| b >= left_bits as u128 ) {
512
- let lint_root = match & self . source_scopes [ source_info. scope ] . local_data {
513
- ClearCrossCrate :: Set ( data) => data. lint_root ,
514
- ClearCrossCrate :: Clear => return None ,
515
- } ;
532
+ let lint_root = self . lint_root ( source_info) ?;
516
533
let dir = if * op == BinOp :: Shr { "right" } else { "left" } ;
517
534
self . tcx . lint_hir (
518
535
:: rustc:: lint:: builtin:: EXCEEDING_BITSHIFTS ,
@@ -570,13 +587,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
570
587
_ => { }
571
588
}
572
589
573
- // `eval_rvalue_into_place` uses `Instance::resolve` for constants which still has a bug
574
- // (#66901) in the presence of trait items with a default body. So we just bail out if we
575
- // aren't 100% monomorphic.
576
- if rvalue. needs_subst ( ) {
577
- return None ;
578
- }
579
-
580
590
self . use_ecx ( source_info, |this| {
581
591
trace ! ( "calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})" , rvalue, place) ;
582
592
this. ecx . eval_rvalue_into_place ( rvalue, place) ?;
@@ -769,18 +779,19 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
769
779
fn visit_constant ( & mut self , constant : & mut Constant < ' tcx > , location : Location ) {
770
780
trace ! ( "visit_constant: {:?}" , constant) ;
771
781
self . super_constant ( constant, location) ;
772
- self . eval_constant ( constant) ;
782
+ self . eval_constant ( constant, self . source_info . unwrap ( ) ) ;
773
783
}
774
784
775
785
fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
776
786
trace ! ( "visit_statement: {:?}" , statement) ;
787
+ let source_info = statement. source_info ;
788
+ self . source_info = Some ( source_info) ;
777
789
if let StatementKind :: Assign ( box ( ref place, ref mut rval) ) = statement. kind {
778
790
let place_ty: Ty < ' tcx > = place. ty ( & self . local_decls , self . tcx ) . ty ;
779
791
if let Ok ( place_layout) = self . tcx . layout_of ( self . param_env . and ( place_ty) ) {
780
792
if let Some ( local) = place. as_local ( ) {
781
- let source = statement. source_info ;
782
793
let can_const_prop = self . can_const_prop [ local] ;
783
- if let Some ( ( ) ) = self . const_prop ( rval, place_layout, source , place) {
794
+ if let Some ( ( ) ) = self . const_prop ( rval, place_layout, source_info , place) {
784
795
if can_const_prop == ConstPropMode :: FullConstProp
785
796
|| can_const_prop == ConstPropMode :: OnlyPropagateInto
786
797
{
@@ -823,8 +834,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
823
834
}
824
835
825
836
fn visit_terminator ( & mut self , terminator : & mut Terminator < ' tcx > , location : Location ) {
826
- self . super_terminator ( terminator, location) ;
827
837
let source_info = terminator. source_info ;
838
+ self . source_info = Some ( source_info) ;
839
+ self . super_terminator ( terminator, location) ;
828
840
match & mut terminator. kind {
829
841
TerminatorKind :: Assert { expected, ref msg, ref mut cond, .. } => {
830
842
if let Some ( value) = self . eval_operand ( & cond, source_info) {
0 commit comments