@@ -1297,102 +1297,172 @@ impl LateLintPass for UnionsWithDropFields {
12971297 }
12981298}
12991299
1300- /// Lint for unions that contain fields with possibly non-trivial destructors.
1300+ /// Lints for non-portable integer conversions.
1301+ pub struct NonPortable1632 ;
13011302pub struct NonPortable3264 ;
1303+ pub struct NonPortable64128 ;
13021304
1305+ declare_lint ! {
1306+ NONPORTABLE_16_32 ,
1307+ Allow ,
1308+ "conversions not portable between 32-bit and 16-bit platforms"
1309+ }
13031310declare_lint ! {
13041311 NONPORTABLE_32_64 ,
13051312 Warn ,
13061313 "conversions not portable between 64-bit and 32-bit platforms"
13071314}
1315+ declare_lint ! {
1316+ NONPORTABLE_64_128 ,
1317+ Allow ,
1318+ "conversions not portable between 64-bit and 128-bit platforms"
1319+ }
13081320
1321+ impl LintPass for NonPortable1632 {
1322+ fn get_lints ( & self ) -> LintArray {
1323+ lint_array ! ( NONPORTABLE_16_32 )
1324+ }
1325+ }
13091326impl LintPass for NonPortable3264 {
13101327 fn get_lints ( & self ) -> LintArray {
13111328 lint_array ! ( NONPORTABLE_32_64 )
13121329 }
13131330}
1331+ impl LintPass for NonPortable64128 {
1332+ fn get_lints ( & self ) -> LintArray {
1333+ lint_array ! ( NONPORTABLE_64_128 )
1334+ }
1335+ }
13141336
1315- fn is_nonportable_conv ( src : subst :: Kind , dst : subst :: Kind ) -> bool {
1316- match ( src . as_type ( ) , dst . as_type ( ) ) {
1317- ( Some ( src ) , Some ( dst ) ) => {
1318- use syntax:: ast:: IntTy :: * ;
1319- use syntax :: ast :: UintTy :: * ;
1320- match ( & src. sty , & dst. sty ) {
1321- // All conditional impls from libcore/num/mod.rs
1322- // not including "32" and "64" at the same time.
1323- ( & TyUint ( U64 ) , & TyUint ( Us ) ) |
1324- ( & TyUint ( Us ) , & TyUint ( U16 ) ) |
1325- ( & TyUint ( Us ) , & TyUint ( U32 ) ) |
1326- ( & TyInt ( I64 ) , & TyInt ( Is ) ) |
1327- ( & TyInt ( Is ) , & TyInt ( I16 ) ) |
1328- ( & TyInt ( Is ) , & TyInt ( I32 ) ) |
1329- ( & TyUint ( U32 ) , & TyInt ( Is ) ) |
1330- ( & TyUint ( Us ) , & TyInt ( I32 ) ) |
1331- ( & TyUint ( Us ) , & TyInt ( I64 ) ) => true ,
1332- _ => false ,
1333- }
1337+ mod pred {
1338+ use super :: * ;
1339+ use syntax :: ast :: IntTy :: * ;
1340+ use syntax:: ast:: UintTy :: * ;
1341+
1342+ pub fn is_nonportable_conv_32_64 ( src : & ty :: TypeVariants , dst : & ty :: TypeVariants ) -> bool {
1343+ match ( src , dst ) {
1344+ // All conditional impls from libcore/num/mod.rs
1345+ // not including "32" and "64" at the same time.
1346+ ( & TyUint ( U64 ) , & TyUint ( Us ) ) |
1347+ ( & TyUint ( Us ) , & TyUint ( U16 ) ) |
1348+ ( & TyUint ( Us ) , & TyUint ( U32 ) ) |
1349+ ( & TyInt ( I64 ) , & TyInt ( Is ) ) |
1350+ ( & TyInt ( Is ) , & TyInt ( I16 ) ) |
1351+ ( & TyInt ( Is ) , & TyInt ( I32 ) ) |
1352+ ( & TyUint ( U32 ) , & TyInt ( Is ) ) |
1353+ ( & TyUint ( Us ) , & TyInt ( I32 ) ) |
1354+ ( & TyUint ( Us ) , & TyInt ( I64 ) ) => true ,
1355+ _ => false ,
13341356 }
1357+ }
1358+
1359+ pub fn is_nonportable_conv_16_32 ( src : & ty:: TypeVariants , dst : & ty:: TypeVariants ) -> bool {
1360+ match ( src, dst) {
1361+ // All conditional impls from libcore/num/mod.rs
1362+ // not including "16" and "32" at the same time.
1363+ ( & TyUint ( U32 ) , & TyUint ( Us ) ) |
1364+ ( & TyUint ( Us ) , & TyUint ( U16 ) ) |
1365+ ( & TyInt ( I32 ) , & TyInt ( Is ) ) |
1366+ ( & TyInt ( Is ) , & TyInt ( I16 ) ) |
1367+ ( & TyUint ( U16 ) , & TyInt ( Is ) ) |
1368+ ( & TyUint ( Us ) , & TyInt ( I32 ) ) => true ,
1369+ _ => false ,
1370+ }
1371+ }
1372+
1373+ pub fn is_nonportable_conv_64_128 ( src : & ty:: TypeVariants , dst : & ty:: TypeVariants ) -> bool {
1374+ match ( src, dst) {
1375+ // All conditional impls from libcore/num/mod.rs
1376+ // not including "64" and potentially "128" at the same time.
1377+ ( & TyUint ( Us ) , & TyUint ( U64 ) ) |
1378+ ( & TyInt ( Is ) , & TyInt ( I64 ) ) => true ,
1379+ _ => false ,
1380+ }
1381+ }
1382+ }
1383+
1384+ fn is_nonportable_conv < Pred > ( src : subst:: Kind , dst : subst:: Kind , pred : Pred ) -> bool
1385+ where Pred : Fn ( & ty:: TypeVariants , & ty:: TypeVariants ) -> bool
1386+ {
1387+ match ( src. as_type ( ) , dst. as_type ( ) ) {
1388+ ( Some ( src) , Some ( dst) ) => pred ( & src. sty , & dst. sty ) ,
13351389 _ => false ,
13361390 }
13371391}
13381392
1339- impl LateLintPass for NonPortable3264 {
1340- fn check_expr ( & mut self , cx : & LateContext , e : & hir:: Expr ) {
1341- let tcx = cx. tcx ;
1342- let report_lint = |span, src : subst:: Kind , dst : subst:: Kind | {
1343- let src_ty = src. as_type ( ) . unwrap ( ) ;
1344- let dst_ty = dst. as_type ( ) . unwrap ( ) ;
1345- cx. span_lint ( NONPORTABLE_32_64 , span,
1346- & format ! ( "conversion `{}` -> `{}` is not portable \
1347- between 64-bit and 32-bit platforms", src_ty, dst_ty) ) ;
1348- } ;
1349- match e. node {
1350- hir:: ExprMethodCall ( name, ..) => {
1351- if name. node . as_str ( ) == "into" {
1352- if let Some ( callee) = tcx. tables . borrow ( ) . method_map
1353- . get ( & ty:: MethodCall :: expr ( e. id ) ) . cloned ( ) {
1354- if let ty:: TyFnDef ( def_id, substs, _) = callee. ty . sty {
1355- let ti = tcx. impl_or_trait_item ( def_id) ;
1356- if let ty:: TraitContainer ( trait_def_id) = ti. container ( ) {
1357- if substs. len ( ) == 2 {
1358- if tcx. item_name ( trait_def_id) . as_str ( ) == "Into" {
1359- if is_nonportable_conv ( substs[ 0 ] , substs[ 1 ] ) {
1360- report_lint ( name. span , substs[ 0 ] , substs[ 1 ] ) ;
1361- }
1393+ fn nonportable_check_expr < Pred > ( cx : & LateContext , e : & hir:: Expr , w1 : u8 , w2 : u8 ,
1394+ lint : & ' static Lint , pred : Pred )
1395+ where Pred : Fn ( & ty:: TypeVariants , & ty:: TypeVariants ) -> bool
1396+ {
1397+ let tcx = cx. tcx ;
1398+ let report_lint = |span, src : subst:: Kind , dst : subst:: Kind | {
1399+ let src_ty = src. as_type ( ) . unwrap ( ) ;
1400+ let dst_ty = dst. as_type ( ) . unwrap ( ) ;
1401+ cx. span_lint ( lint, span,
1402+ & format ! ( "conversion `{}` -> `{}` is not portable \
1403+ between {}-bit and {}-bit platforms", src_ty, dst_ty, w1, w2) ) ;
1404+ } ;
1405+ match e. node {
1406+ hir:: ExprMethodCall ( name, ..) => {
1407+ if name. node . as_str ( ) == "into" {
1408+ if let Some ( callee) = tcx. tables . borrow ( ) . method_map
1409+ . get ( & ty:: MethodCall :: expr ( e. id ) ) . cloned ( ) {
1410+ if let ty:: TyFnDef ( def_id, substs, _) = callee. ty . sty {
1411+ let ti = tcx. impl_or_trait_item ( def_id) ;
1412+ if let ty:: TraitContainer ( trait_def_id) = ti. container ( ) {
1413+ if substs. len ( ) == 2 {
1414+ if tcx. item_name ( trait_def_id) . as_str ( ) == "Into" {
1415+ if is_nonportable_conv ( substs[ 0 ] , substs[ 1 ] , pred) {
1416+ report_lint ( name. span , substs[ 0 ] , substs[ 1 ] ) ;
13621417 }
13631418 }
13641419 }
13651420 }
13661421 }
13671422 }
13681423 }
1369- hir :: ExprPath ( .. ) => {
1370- if let Def :: Method ( def_id ) = tcx . expect_def ( e . id ) {
1371- let ti = tcx. impl_or_trait_item ( def_id ) ;
1372- if let ty :: MethodTraitItem ( ref method ) = ti {
1373- if let ty:: TraitContainer ( trait_def_id ) = ti. container ( ) {
1374- let substs = tcx . node_id_item_substs ( e . id ) . substs ;
1375- if substs . len ( ) == 2 {
1376- if method . name . as_str ( ) == "into" {
1377- if tcx . item_name ( trait_def_id ) . as_str ( ) == "Into " {
1378- if is_nonportable_conv ( substs [ 0 ] , substs [ 1 ] ) {
1379- report_lint ( e . span , substs[ 0 ] , substs[ 1 ] ) ;
1380- }
1424+ }
1425+ hir :: ExprPath ( .. ) => {
1426+ if let Def :: Method ( def_id ) = tcx. expect_def ( e . id ) {
1427+ let ti = tcx . impl_or_trait_item ( def_id ) ;
1428+ if let ty:: MethodTraitItem ( ref method ) = ti {
1429+ if let ty :: TraitContainer ( trait_def_id ) = ti . container ( ) {
1430+ let substs = tcx . node_id_item_substs ( e . id ) . substs ;
1431+ if substs . len ( ) == 2 {
1432+ if method . name . as_str ( ) == "into " {
1433+ if tcx . item_name ( trait_def_id ) . as_str ( ) == "Into" {
1434+ if is_nonportable_conv ( substs[ 0 ] , substs[ 1 ] , pred ) {
1435+ report_lint ( e . span , substs [ 0 ] , substs [ 1 ] ) ;
13811436 }
13821437 }
1383- if method. name . as_str ( ) == "from" {
1384- if tcx. item_name ( trait_def_id) . as_str ( ) == "From" {
1385- if is_nonportable_conv ( substs[ 1 ] , substs[ 0 ] ) {
1386- report_lint ( e. span , substs[ 1 ] , substs[ 0 ] ) ;
1387- }
1438+ } else if method. name . as_str ( ) == "from" {
1439+ if tcx. item_name ( trait_def_id) . as_str ( ) == "From" {
1440+ if is_nonportable_conv ( substs[ 1 ] , substs[ 0 ] , pred) {
1441+ report_lint ( e. span , substs[ 1 ] , substs[ 0 ] ) ;
13881442 }
13891443 }
13901444 }
13911445 }
13921446 }
13931447 }
13941448 }
1395- _ => { }
13961449 }
1450+ _ => { }
1451+ }
1452+ }
1453+
1454+ impl LateLintPass for NonPortable1632 {
1455+ fn check_expr ( & mut self , cx : & LateContext , e : & hir:: Expr ) {
1456+ nonportable_check_expr ( cx, e, 32 , 16 , NONPORTABLE_16_32 , pred:: is_nonportable_conv_16_32)
1457+ }
1458+ }
1459+ impl LateLintPass for NonPortable3264 {
1460+ fn check_expr ( & mut self , cx : & LateContext , e : & hir:: Expr ) {
1461+ nonportable_check_expr ( cx, e, 64 , 32 , NONPORTABLE_32_64 , pred:: is_nonportable_conv_32_64)
1462+ }
1463+ }
1464+ impl LateLintPass for NonPortable64128 {
1465+ fn check_expr ( & mut self , cx : & LateContext , e : & hir:: Expr ) {
1466+ nonportable_check_expr ( cx, e, 64 , 128 , NONPORTABLE_64_128 , pred:: is_nonportable_conv_64_128)
13971467 }
13981468}
0 commit comments