@@ -23,7 +23,7 @@ use hair::util::UserAnnotatedTyHelpers;
23
23
use rustc:: mir:: { fmt_const_val, Field , BorrowKind , Mutability } ;
24
24
use rustc:: mir:: { ProjectionElem , UserTypeAnnotation , UserTypeProjection , UserTypeProjections } ;
25
25
use 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 } ;
27
27
use rustc:: ty:: subst:: { Substs , Kind } ;
28
28
use rustc:: ty:: layout:: VariantIdx ;
29
29
use rustc:: hir:: { self , PatKind , RangeEnd } ;
@@ -891,12 +891,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
891
891
) ;
892
892
* self . const_to_pat ( instance, val, expr. hir_id , lit. span ) . kind
893
893
} ,
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 ) ;
898
896
PatternKind :: Wild
899
897
} ,
898
+ Err ( LitToConstError :: Reported ) => PatternKind :: Wild ,
900
899
}
901
900
} ,
902
901
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> {
914
913
) ;
915
914
* self . const_to_pat ( instance, val, expr. hir_id , lit. span ) . kind
916
915
} ,
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 ) ;
921
918
PatternKind :: Wild
922
919
} ,
920
+ Err ( LitToConstError :: Reported ) => PatternKind :: Wild ,
923
921
}
924
922
}
925
923
_ => span_bug ! ( expr. span, "not a literal: {:?}" , expr) ,
@@ -1296,19 +1294,32 @@ pub fn compare_const_vals<'a, 'tcx>(
1296
1294
}
1297
1295
1298
1296
#[ derive( PartialEq ) ]
1299
- enum LitToConstError {
1297
+ pub enum LitToConstError {
1300
1298
UnparseableFloat ,
1301
- Propagated ,
1299
+ Reported ,
1302
1300
}
1303
1301
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 > {
1310
1308
use syntax:: ast:: * ;
1311
1309
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
+
1312
1323
use rustc:: mir:: interpret:: * ;
1313
1324
let lit = match * lit {
1314
1325
LitKind :: Str ( ref s, _) => {
@@ -1324,48 +1335,12 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
1324
1335
bits : n as u128 ,
1325
1336
size : 1 ,
1326
1337
} ) ,
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 ) ?
1368
1342
} ,
1343
+ LitKind :: Int ( n, _) => trunc ( n) ?,
1369
1344
LitKind :: Float ( n, fty) => {
1370
1345
parse_float ( n, fty, neg) . map_err ( |_| LitToConstError :: UnparseableFloat ) ?
1371
1346
}
0 commit comments