@@ -12,10 +12,10 @@ use rustc::mir::visit::{
12
12
MutVisitor , MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor ,
13
13
} ;
14
14
use rustc:: mir:: {
15
- read_only, AggregateKind , BasicBlock , BinOp , Body , BodyAndCache , ClearCrossCrate , Constant ,
16
- Local , LocalDecl , LocalKind , Location , Operand , Place , PlaceBase , ReadOnlyBodyAndCache , Rvalue ,
17
- SourceInfo , SourceScope , SourceScopeData , Statement , StatementKind , Terminator , TerminatorKind ,
18
- UnOp , RETURN_PLACE ,
15
+ read_only, AggregateKind , BasicBlock , BinOp , Body , BodyAndCache , CastKind , ClearCrossCrate ,
16
+ Constant , Local , LocalDecl , LocalKind , Location , Operand , Place , PlaceBase ,
17
+ ReadOnlyBodyAndCache , Rvalue , SourceInfo , SourceScope , SourceScopeData , Statement ,
18
+ StatementKind , Terminator , TerminatorKind , UnOp , RETURN_PLACE ,
19
19
} ;
20
20
use rustc:: ty:: layout:: {
21
21
HasDataLayout , HasTyCtxt , LayoutError , LayoutOf , Size , TargetDataLayout , TyLayout ,
@@ -29,9 +29,9 @@ use syntax_pos::{Span, DUMMY_SP};
29
29
30
30
use crate :: const_eval:: error_to_const_error;
31
31
use crate :: interpret:: {
32
- self , intern_const_alloc_recursive, AllocId , Allocation , Frame , ImmTy , Immediate , InterpCx ,
33
- LocalState , LocalValue , Memory , MemoryKind , OpTy , Operand as InterpOperand , PlaceTy , Pointer ,
34
- ScalarMaybeUndef , StackPopCleanup ,
32
+ self , intern_const_alloc_recursive, truncate , AllocId , Allocation , Frame , ImmTy , Immediate ,
33
+ InterpCx , LocalState , LocalValue , Memory , MemoryKind , OpTy , Operand as InterpOperand , PlaceTy ,
34
+ Pointer , ScalarMaybeUndef , StackPopCleanup ,
35
35
} ;
36
36
use crate :: rustc:: ty:: subst:: Subst ;
37
37
use crate :: transform:: { MirPass , MirSource } ;
@@ -584,6 +584,45 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
584
584
}
585
585
}
586
586
587
+ Rvalue :: Cast ( CastKind :: Misc , op, ty) => {
588
+ trace ! ( "checking Cast(Misc, {:?}, {:?})" , op, ty) ;
589
+
590
+ if ty. is_integral ( ) && op. ty ( & self . local_decls , self . tcx ) . is_integral ( ) {
591
+ let value = self . use_ecx ( source_info, |this| {
592
+ this. ecx . read_immediate ( this. ecx . eval_operand ( op, None ) ?)
593
+ } ) ?;
594
+
595
+ // Do not try to read bits for ZSTs
596
+ if !value. layout . is_zst ( ) {
597
+ let value_size = value. layout . size ;
598
+ let value_bits = value. to_scalar ( ) . and_then ( |r| r. to_bits ( value_size) ) ;
599
+ if let Ok ( value_bits) = value_bits {
600
+ let truncated = truncate ( value_bits, place_layout. size ) ;
601
+ if truncated != value_bits {
602
+ let scope = source_info. scope ;
603
+ let lint_root = match & self . source_scopes [ scope] . local_data {
604
+ ClearCrossCrate :: Set ( data) => data. lint_root ,
605
+ ClearCrossCrate :: Clear => return None ,
606
+ } ;
607
+ self . tcx . lint_hir (
608
+ :: rustc:: lint:: builtin:: CONST_ERR ,
609
+ lint_root,
610
+ span,
611
+ & format ! (
612
+ "truncating cast: the value {} requires {} bits but \
613
+ the target type is only {} bits",
614
+ value_bits,
615
+ value_size. bits( ) ,
616
+ place_layout. size. bits( )
617
+ ) ,
618
+ ) ;
619
+ return None ;
620
+ }
621
+ }
622
+ }
623
+ }
624
+ }
625
+
587
626
_ => { }
588
627
}
589
628
0 commit comments