@@ -12,10 +12,10 @@ use rustc::mir::visit::{
1212 MutVisitor , MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor ,
1313} ;
1414use 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 ,
1919} ;
2020use rustc:: ty:: layout:: {
2121 HasDataLayout , HasTyCtxt , LayoutError , LayoutOf , Size , TargetDataLayout , TyLayout ,
@@ -29,9 +29,9 @@ use syntax_pos::{Span, DUMMY_SP};
2929
3030use crate :: const_eval:: error_to_const_error;
3131use 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 ,
3535} ;
3636use crate :: rustc:: ty:: subst:: Subst ;
3737use crate :: transform:: { MirPass , MirSource } ;
@@ -584,6 +584,45 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
584584 }
585585 }
586586
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+
587626 _ => { }
588627 }
589628
0 commit comments