@@ -23,7 +23,7 @@ use hair::util::UserAnnotatedTyHelpers;
2323use rustc:: mir:: { fmt_const_val, Field , BorrowKind , Mutability } ;
2424use rustc:: mir:: { ProjectionElem , UserTypeAnnotation , UserTypeProjection , UserTypeProjections } ;
2525use rustc:: mir:: interpret:: { Scalar , GlobalId , ConstValue , sign_extend} ;
26- use rustc:: ty:: { self , Region , TyCtxt , AdtDef , Ty } ;
26+ use rustc:: ty:: { self , Region , TyCtxt , AdtDef , Ty , ParamEnv } ;
2727use rustc:: ty:: subst:: { Substs , Kind } ;
2828use rustc:: ty:: layout:: VariantIdx ;
2929use rustc:: hir:: { self , PatKind , RangeEnd } ;
@@ -891,12 +891,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
891891 ) ;
892892 * self . const_to_pat ( instance, val, expr. hir_id , lit. span ) . kind
893893 } ,
894- Err ( e) => {
895- if e == LitToConstError :: UnparseableFloat {
896- self . errors . push ( PatternError :: FloatBug ) ;
897- }
894+ Err ( LitToConstError :: UnparseableFloat ) => {
895+ self . errors . push ( PatternError :: FloatBug ) ;
898896 PatternKind :: Wild
899897 } ,
898+ Err ( LitToConstError :: Reported ) => PatternKind :: Wild ,
900899 }
901900 } ,
902901 hir:: ExprKind :: Path ( ref qpath) => * self . lower_path ( qpath, expr. hir_id , expr. span ) . kind ,
@@ -914,12 +913,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
914913 ) ;
915914 * self . const_to_pat ( instance, val, expr. hir_id , lit. span ) . kind
916915 } ,
917- Err ( e) => {
918- if e == LitToConstError :: UnparseableFloat {
919- self . errors . push ( PatternError :: FloatBug ) ;
920- }
916+ Err ( LitToConstError :: UnparseableFloat ) => {
917+ self . errors . push ( PatternError :: FloatBug ) ;
921918 PatternKind :: Wild
922919 } ,
920+ Err ( LitToConstError :: Reported ) => PatternKind :: Wild ,
923921 }
924922 }
925923 _ => span_bug ! ( expr. span, "not a literal: {:?}" , expr) ,
@@ -1296,19 +1294,32 @@ pub fn compare_const_vals<'a, 'tcx>(
12961294}
12971295
12981296#[ derive( PartialEq ) ]
1299- enum LitToConstError {
1297+ pub enum LitToConstError {
13001298 UnparseableFloat ,
1301- Propagated ,
1299+ Reported ,
13021300}
13031301
1304- // FIXME: Combine with rustc_mir::hair::cx::const_eval_literal
1305- fn lit_to_const < ' a , ' tcx > ( lit : & ' tcx ast:: LitKind ,
1306- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1307- ty : Ty < ' tcx > ,
1308- neg : bool )
1309- -> Result < & ' tcx ty:: Const < ' tcx > , LitToConstError > {
1302+ pub fn lit_to_const < ' a , ' gcx , ' tcx > (
1303+ lit : & ' tcx ast:: LitKind ,
1304+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
1305+ ty : Ty < ' tcx > ,
1306+ neg : bool ,
1307+ ) -> Result < & ' tcx ty:: Const < ' tcx > , LitToConstError > {
13101308 use syntax:: ast:: * ;
13111309
1310+ let trunc = |n| {
1311+ let param_ty = ParamEnv :: reveal_all ( ) . and ( tcx. lift_to_global ( & ty) . unwrap ( ) ) ;
1312+ let width = tcx. layout_of ( param_ty) . map_err ( |_| LitToConstError :: Reported ) ?. size ;
1313+ trace ! ( "trunc {} with size {} and shift {}" , n, width. bits( ) , 128 - width. bits( ) ) ;
1314+ let shift = 128 - width. bits ( ) ;
1315+ let result = ( n << shift) >> shift;
1316+ trace ! ( "trunc result: {}" , result) ;
1317+ Ok ( ConstValue :: Scalar ( Scalar :: Bits {
1318+ bits : result,
1319+ size : width. bytes ( ) as u8 ,
1320+ } ) )
1321+ } ;
1322+
13121323 use rustc:: mir:: interpret:: * ;
13131324 let lit = match * lit {
13141325 LitKind :: Str ( ref s, _) => {
@@ -1324,48 +1335,12 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
13241335 bits : n as u128 ,
13251336 size : 1 ,
13261337 } ) ,
1327- LitKind :: Int ( n, _) => {
1328- enum Int {
1329- Signed ( IntTy ) ,
1330- Unsigned ( UintTy ) ,
1331- }
1332- let ity = match ty. sty {
1333- ty:: Int ( IntTy :: Isize ) => Int :: Signed ( tcx. sess . target . isize_ty ) ,
1334- ty:: Int ( other) => Int :: Signed ( other) ,
1335- ty:: Uint ( UintTy :: Usize ) => Int :: Unsigned ( tcx. sess . target . usize_ty ) ,
1336- ty:: Uint ( other) => Int :: Unsigned ( other) ,
1337- ty:: Error => { // Avoid ICE (#51963)
1338- return Err ( LitToConstError :: Propagated ) ;
1339- }
1340- _ => bug ! ( "literal integer type with bad type ({:?})" , ty. sty) ,
1341- } ;
1342- // This converts from LitKind::Int (which is sign extended) to
1343- // Scalar::Bytes (which is zero extended)
1344- let n = match ity {
1345- // FIXME(oli-obk): are these casts correct?
1346- Int :: Signed ( IntTy :: I8 ) if neg =>
1347- ( n as i8 ) . overflowing_neg ( ) . 0 as u8 as u128 ,
1348- Int :: Signed ( IntTy :: I16 ) if neg =>
1349- ( n as i16 ) . overflowing_neg ( ) . 0 as u16 as u128 ,
1350- Int :: Signed ( IntTy :: I32 ) if neg =>
1351- ( n as i32 ) . overflowing_neg ( ) . 0 as u32 as u128 ,
1352- Int :: Signed ( IntTy :: I64 ) if neg =>
1353- ( n as i64 ) . overflowing_neg ( ) . 0 as u64 as u128 ,
1354- Int :: Signed ( IntTy :: I128 ) if neg =>
1355- ( n as i128 ) . overflowing_neg ( ) . 0 as u128 ,
1356- Int :: Signed ( IntTy :: I8 ) | Int :: Unsigned ( UintTy :: U8 ) => n as u8 as u128 ,
1357- Int :: Signed ( IntTy :: I16 ) | Int :: Unsigned ( UintTy :: U16 ) => n as u16 as u128 ,
1358- Int :: Signed ( IntTy :: I32 ) | Int :: Unsigned ( UintTy :: U32 ) => n as u32 as u128 ,
1359- Int :: Signed ( IntTy :: I64 ) | Int :: Unsigned ( UintTy :: U64 ) => n as u64 as u128 ,
1360- Int :: Signed ( IntTy :: I128 ) | Int :: Unsigned ( UintTy :: U128 ) => n,
1361- _ => bug ! ( ) ,
1362- } ;
1363- let size = tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) . size . bytes ( ) as u8 ;
1364- ConstValue :: Scalar ( Scalar :: Bits {
1365- bits : n,
1366- size,
1367- } )
1338+ LitKind :: Int ( n, _) if neg => {
1339+ let n = n as i128 ;
1340+ let n = n. overflowing_neg ( ) . 0 ;
1341+ trunc ( n as u128 ) ?
13681342 } ,
1343+ LitKind :: Int ( n, _) => trunc ( n) ?,
13691344 LitKind :: Float ( n, fty) => {
13701345 parse_float ( n, fty, neg) . map_err ( |_| LitToConstError :: UnparseableFloat ) ?
13711346 }
0 commit comments