Skip to content

Commit 7075015

Browse files
author
Abroskin Alexander
authored
Merge branch 'master' into add-lints-aseert-checks
2 parents 906b516 + 5b84966 commit 7075015

File tree

10 files changed

+173
-24
lines changed

10 files changed

+173
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ All notable changes to this project will be documented in this file.
635635
[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap
636636
[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
637637
[`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ptr_alignment
638+
[`cast_ref_to_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ref_to_mut
638639
[`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_sign_loss
639640
[`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8
640641
[`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp

README.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,7 @@
77

88
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
99

10-
<<<<<<< HEAD
1110
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
12-
||||||| merged common ancestors
13-
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
14-
=======
15-
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
16-
>>>>>>> run ./util/dev update_lints
1711

1812
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1913

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
487487
reg.register_late_lint_pass(box ptr_offset_with_cast::Pass);
488488
reg.register_late_lint_pass(box redundant_clone::RedundantClone);
489489
reg.register_late_lint_pass(box slow_vector_initialization::Pass);
490+
reg.register_late_lint_pass(box types::RefToMut);
490491
reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants);
491492

492493
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
@@ -761,6 +762,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
761762
types::BOX_VEC,
762763
types::CAST_LOSSLESS,
763764
types::CAST_PTR_ALIGNMENT,
765+
types::CAST_REF_TO_MUT,
764766
types::CHAR_LIT_AS_U8,
765767
types::FN_TO_NUMERIC_CAST,
766768
types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
@@ -993,6 +995,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
993995
transmute::WRONG_TRANSMUTE,
994996
types::ABSURD_EXTREME_COMPARISONS,
995997
types::CAST_PTR_ALIGNMENT,
998+
types::CAST_REF_TO_MUT,
996999
types::UNIT_CMP,
9971000
unicode::ZERO_WIDTH_SPACE,
9981001
unused_io_amount::UNUSED_IO_AMOUNT,

clippy_lints/src/new_without_default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use syntax::source_map::Span;
2727
/// It detects both the case when a manual
2828
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
2929
/// implementation is required and also when it can be created with
30-
/// `#[derive(Default)]
30+
/// `#[derive(Default)]`
3131
///
3232
/// **Why is this bad?** The user might expect to be able to use
3333
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the

clippy_lints/src/types.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,3 +2240,64 @@ impl<'a, 'b, 'tcx: 'a + 'b> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'
22402240
NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir())
22412241
}
22422242
}
2243+
2244+
/// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
2245+
///
2246+
/// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
2247+
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
2248+
/// mutable.
2249+
///
2250+
/// **Known problems:** None.
2251+
///
2252+
/// **Example:**
2253+
/// ```rust
2254+
/// fn x(r: &i32) {
2255+
/// unsafe {
2256+
/// *(r as *const _ as *mut _) += 1;
2257+
/// }
2258+
/// }
2259+
/// ```
2260+
///
2261+
/// Instead consider using interior mutability types.
2262+
///
2263+
/// ```rust
2264+
/// fn x(r: &UnsafeCell<i32>) {
2265+
/// unsafe {
2266+
/// *r.get() += 1;
2267+
/// }
2268+
/// }
2269+
/// ```
2270+
declare_clippy_lint! {
2271+
pub CAST_REF_TO_MUT,
2272+
correctness,
2273+
"a cast of reference to a mutable pointer"
2274+
}
2275+
2276+
pub struct RefToMut;
2277+
2278+
impl LintPass for RefToMut {
2279+
fn get_lints(&self) -> LintArray {
2280+
lint_array!(CAST_REF_TO_MUT)
2281+
}
2282+
}
2283+
2284+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut {
2285+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
2286+
if_chain! {
2287+
if let ExprKind::Unary(UnOp::UnDeref, e) = &expr.node;
2288+
if let ExprKind::Cast(e, t) = &e.node;
2289+
if let TyKind::Ptr(MutTy { mutbl: Mutability::MutMutable, .. }) = t.node;
2290+
if let ExprKind::Cast(e, t) = &e.node;
2291+
if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node;
2292+
if let ty::Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty;
2293+
then {
2294+
span_lint(
2295+
cx,
2296+
CAST_REF_TO_MUT,
2297+
expr.span,
2298+
"casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell",
2299+
);
2300+
}
2301+
}
2302+
}
2303+
}

clippy_lints/src/use_self.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@
1010
use crate::utils::span_lint_and_sugg;
1111
use if_chain::if_chain;
1212
use rustc::hir::def::{CtorKind, Def};
13-
use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor};
13+
use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Visitor};
1414
use rustc::hir::*;
1515
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
1616
use rustc::ty;
1717
use rustc::{declare_tool_lint, lint_array};
1818
use rustc_errors::Applicability;
19-
use syntax::ast::NodeId;
2019
use syntax_pos::symbol::keywords::SelfUpper;
2120

2221
/// **What it does:** Checks for unnecessary repetition of structure name when a
@@ -29,7 +28,6 @@ use syntax_pos::symbol::keywords::SelfUpper;
2928
/// **Known problems:**
3029
/// - False positive when using associated types (#2843)
3130
/// - False positives in some situations when using generics (#3410)
32-
/// - False positive when type from outer function can't be used (#3463)
3331
///
3432
/// **Example:**
3533
/// ```rust
@@ -242,8 +240,18 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
242240
walk_path(self, path);
243241
}
244242

245-
fn visit_use(&mut self, _path: &'tcx Path, _id: NodeId, _hir_id: HirId) {
246-
// Don't check use statements
243+
fn visit_item(&mut self, item: &'tcx Item) {
244+
match item.node {
245+
ItemKind::Use(..)
246+
| ItemKind::Static(..)
247+
| ItemKind::Enum(..)
248+
| ItemKind::Struct(..)
249+
| ItemKind::Union(..)
250+
| ItemKind::Impl(..) => {
251+
// Don't check statements that shadow `Self` or where `Self` can't be used
252+
},
253+
_ => walk_item(self, item),
254+
}
247255
}
248256

249257
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {

tests/ui/cast_ref_to_mut.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![warn(clippy::cast_ref_to_mut)]
2+
#![allow(clippy::no_effect)]
3+
4+
extern "C" {
5+
// NB. Mutability can be easily incorrect in FFI calls, as
6+
// in C, the default are mutable pointers.
7+
fn ffi(c: *mut u8);
8+
fn int_ffi(c: *mut i32);
9+
}
10+
11+
fn main() {
12+
let s = String::from("Hello");
13+
let a = &s;
14+
unsafe {
15+
let num = &3i32;
16+
let mut_num = &mut 3i32;
17+
// Should be warned against
18+
(*(a as *const _ as *mut String)).push_str(" world");
19+
*(a as *const _ as *mut _) = String::from("Replaced");
20+
*(a as *const _ as *mut String) += " world";
21+
// Shouldn't be warned against
22+
println!("{}", *(num as *const _ as *const i16));
23+
println!("{}", *(mut_num as *mut _ as *mut i16));
24+
ffi(a.as_ptr() as *mut _);
25+
int_ffi(num as *const _ as *mut _);
26+
int_ffi(&3 as *const _ as *mut _);
27+
let mut value = 3;
28+
let value: *const i32 = &mut value;
29+
*(value as *const i16 as *mut i16) = 42;
30+
}
31+
}

tests/ui/cast_ref_to_mut.stderr

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell
2+
--> $DIR/cast_ref_to_mut.rs:18:9
3+
|
4+
LL | (*(a as *const _ as *mut String)).push_str(" world");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::cast-ref-to-mut` implied by `-D warnings`
8+
9+
error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell
10+
--> $DIR/cast_ref_to_mut.rs:19:9
11+
|
12+
LL | *(a as *const _ as *mut _) = String::from("Replaced");
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell
16+
--> $DIR/cast_ref_to_mut.rs:20:9
17+
|
18+
LL | *(a as *const _ as *mut String) += " world";
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 3 previous errors
22+

tests/ui/use_self.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,34 @@ mod macros {
242242
}
243243
}
244244

245+
mod nesting {
246+
struct Foo {}
247+
impl Foo {
248+
fn foo() {
249+
use self::Foo; // Can't use Self here
250+
struct Bar {
251+
foo: Foo, // Foo != Self
252+
}
253+
254+
impl Bar {
255+
fn bar() -> Bar {
256+
Bar { foo: Foo {} }
257+
}
258+
}
259+
}
260+
}
261+
262+
enum Enum {
263+
A,
264+
}
265+
impl Enum {
266+
fn method() {
267+
use self::Enum::*; // Issue 3425
268+
static STATIC: Enum = Enum::A; // Can't use Self as type
269+
}
270+
}
271+
}
272+
245273
mod issue3410 {
246274

247275
struct A;
@@ -255,14 +283,3 @@ mod issue3410 {
255283
fn a(_: Vec<A>) {}
256284
}
257285
}
258-
259-
mod issue3425 {
260-
enum Enum {
261-
A,
262-
}
263-
impl Enum {
264-
fn a() {
265-
use self::Enum::*;
266-
}
267-
}
268-
}

tests/ui/use_self.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,17 @@ LL | Foo {}
150150
LL | use_self_expand!(); // Should lint in local macros
151151
| ------------------- in this macro invocation
152152

153-
error: aborting due to 24 previous errors
153+
error: unnecessary structure name repetition
154+
--> $DIR/use_self.rs:255:29
155+
|
156+
LL | fn bar() -> Bar {
157+
| ^^^ help: use the applicable keyword: `Self`
158+
159+
error: unnecessary structure name repetition
160+
--> $DIR/use_self.rs:256:21
161+
|
162+
LL | Bar { foo: Foo {} }
163+
| ^^^ help: use the applicable keyword: `Self`
164+
165+
error: aborting due to 26 previous errors
154166

0 commit comments

Comments
 (0)