diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ca30ed4a536e2..142c5a7e801b5 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1265,3 +1265,54 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { } } } + + +/// Lint for casts from types other than `usize` or `isize` to raw pointers +pub struct IntoToRawPtrCast; + +declare_lint! { + pub INT_TO_RAW_PTR_CAST, + Deny, + "cast from signed int other than `isize` to raw pointer" +} + +impl LintPass for IntoToRawPtrCast { + fn get_lints(&self) -> LintArray { + lint_array!(INT_TO_RAW_PTR_CAST) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IntoToRawPtrCast { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { + if let hir::ExprCast(ref base, _) = expr.node { + let base_ty = cx.tables.expr_ty(base); + let target_ty = cx.tables.expr_ty(expr); + if let ty::TyRawPtr(..) = target_ty.sty { + match base_ty.sty { + ty::TyInt(ast::IntTy::Is) | + ty::TyInt(ast::IntTy::I128) | + ty::TyInt(ast::IntTy::I64) => return, + ty::TyInt(ast::IntTy::I32) => { + if cx.tcx.data_layout.pointer_size.bytes() <= 4 { + return; + } + }, + ty::TyInt(ast::IntTy::I16) => { + if cx.tcx.data_layout.pointer_size.bytes() <= 2 { + return; + } + }, + // these we report + ty::TyInt(_) => {}, + // only int casts are relevant + _ => return, + } + cx.span_lint( + INT_TO_RAW_PTR_CAST, + expr.span, + &format!("cast from `{}` to raw pointer", base_ty), + ); + } + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 83c00c178a0ba..18d7da0f50bad 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -142,6 +142,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { PluginAsLibrary, MutableTransmutes, UnionsWithDropFields, + IntoToRawPtrCast, ); add_builtin_with_new!(sess, @@ -241,6 +242,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS), reference: "issue #42868 ", }, + FutureIncompatibleInfo { + id: LintId::of(builtin::INT_TO_RAW_PTR_CAST), + reference: "issue #43291 ", + }, ]); // Register renamed and removed lints diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index ce6fd4cb0754b..8a9fe783aa5bf 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -48,7 +48,7 @@ pub fn cleanup() { unsafe { LOCK.lock(); let queue = QUEUE; - QUEUE = if i == ITERS - 1 {1} else {0} as *mut _; + QUEUE = if i == ITERS - 1 {1usize} else {0usize} as *mut _; LOCK.unlock(); // make sure we're not recursively cleaning up diff --git a/src/test/run-pass/cast-to-infer-ty.rs b/src/test/run-pass/cast-to-infer-ty.rs index 2aa0d9c62fb41..6724ea559f273 100644 --- a/src/test/run-pass/cast-to-infer-ty.rs +++ b/src/test/run-pass/cast-to-infer-ty.rs @@ -11,6 +11,8 @@ // Check that we allow a cast to `_` so long as the target type can be // inferred elsewhere. +#[allow(int_to_raw_ptr_cast)] + pub fn main() { let i: *const i32 = 0 as _; assert!(i.is_null()); diff --git a/src/test/run-pass/mir_misc_casts.rs b/src/test/run-pass/mir_misc_casts.rs index ae719ac2800ee..d566ce109c5ee 100644 --- a/src/test/run-pass/mir_misc_casts.rs +++ b/src/test/run-pass/mir_misc_casts.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(libc)] +#![allow(int_to_raw_ptr_cast)] extern crate libc; diff --git a/src/test/run-pass/supported-cast.rs b/src/test/run-pass/supported-cast.rs index a47ae52f5902c..90edc85d4d6f2 100644 --- a/src/test/run-pass/supported-cast.rs +++ b/src/test/run-pass/supported-cast.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(libc)] +#![allow(int_to_raw_ptr_cast)] extern crate libc;