mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
Merge branch 'master' into add-lints-aseert-checks
This commit is contained in:
@@ -635,6 +635,7 @@ All notable changes to this project will be documented in this file.
|
||||
[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap
|
||||
[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
|
||||
[`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ptr_alignment
|
||||
[`cast_ref_to_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ref_to_mut
|
||||
[`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_sign_loss
|
||||
[`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8
|
||||
[`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp
|
||||
|
||||
@@ -7,13 +7,7 @@
|
||||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
<<<<<<< HEAD
|
||||
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
||||||| merged common ancestors
|
||||
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
=======
|
||||
[There are 291 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
>>>>>>> run ./util/dev update_lints
|
||||
|
||||
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
|
||||
|
||||
|
||||
@@ -487,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||
reg.register_late_lint_pass(box ptr_offset_with_cast::Pass);
|
||||
reg.register_late_lint_pass(box redundant_clone::RedundantClone);
|
||||
reg.register_late_lint_pass(box slow_vector_initialization::Pass);
|
||||
reg.register_late_lint_pass(box types::RefToMut);
|
||||
reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants);
|
||||
|
||||
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec
|
||||
/// implementation is required and also when it can be created with
|
||||
/// `#[derive(Default)]
|
||||
/// `#[derive(Default)]`
|
||||
///
|
||||
/// **Why is this bad?** The user might expect to be able to use
|
||||
/// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
|
||||
|
||||
@@ -2240,3 +2240,64 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir())
|
||||
}
|
||||
}
|
||||
|
||||
/// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
|
||||
///
|
||||
/// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
|
||||
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
|
||||
/// mutable.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// fn x(r: &i32) {
|
||||
/// unsafe {
|
||||
/// *(r as *const _ as *mut _) += 1;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Instead consider using interior mutability types.
|
||||
///
|
||||
/// ```rust
|
||||
/// fn x(r: &UnsafeCell<i32>) {
|
||||
/// unsafe {
|
||||
/// *r.get() += 1;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
declare_clippy_lint! {
|
||||
pub CAST_REF_TO_MUT,
|
||||
correctness,
|
||||
"a cast of reference to a mutable pointer"
|
||||
}
|
||||
|
||||
pub struct RefToMut;
|
||||
|
||||
impl LintPass for RefToMut {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(CAST_REF_TO_MUT)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RefToMut {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
if_chain! {
|
||||
if let ExprKind::Unary(UnOp::UnDeref, e) = &expr.node;
|
||||
if let ExprKind::Cast(e, t) = &e.node;
|
||||
if let TyKind::Ptr(MutTy { mutbl: Mutability::MutMutable, .. }) = t.node;
|
||||
if let ExprKind::Cast(e, t) = &e.node;
|
||||
if let TyKind::Ptr(MutTy { mutbl: Mutability::MutImmutable, .. }) = t.node;
|
||||
if let ty::Ref(..) = cx.tables.node_id_to_type(e.hir_id).sty;
|
||||
then {
|
||||
span_lint(
|
||||
cx,
|
||||
CAST_REF_TO_MUT,
|
||||
expr.span,
|
||||
"casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
use crate::utils::span_lint_and_sugg;
|
||||
use if_chain::if_chain;
|
||||
use rustc::hir::def::{CtorKind, Def};
|
||||
use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor};
|
||||
use rustc::hir::intravisit::{walk_item, walk_path, walk_ty, NestedVisitorMap, Visitor};
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::ty;
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_errors::Applicability;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax_pos::symbol::keywords::SelfUpper;
|
||||
|
||||
/// **What it does:** Checks for unnecessary repetition of structure name when a
|
||||
@@ -29,7 +28,6 @@
|
||||
/// **Known problems:**
|
||||
/// - False positive when using associated types (#2843)
|
||||
/// - False positives in some situations when using generics (#3410)
|
||||
/// - False positive when type from outer function can't be used (#3463)
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
@@ -242,8 +240,18 @@ fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
|
||||
walk_path(self, path);
|
||||
}
|
||||
|
||||
fn visit_use(&mut self, _path: &'tcx Path, _id: NodeId, _hir_id: HirId) {
|
||||
// Don't check use statements
|
||||
fn visit_item(&mut self, item: &'tcx Item) {
|
||||
match item.node {
|
||||
ItemKind::Use(..)
|
||||
| ItemKind::Static(..)
|
||||
| ItemKind::Enum(..)
|
||||
| ItemKind::Struct(..)
|
||||
| ItemKind::Union(..)
|
||||
| ItemKind::Impl(..) => {
|
||||
// Don't check statements that shadow `Self` or where `Self` can't be used
|
||||
},
|
||||
_ => walk_item(self, item),
|
||||
}
|
||||
}
|
||||
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#![warn(clippy::cast_ref_to_mut)]
|
||||
#![allow(clippy::no_effect)]
|
||||
|
||||
extern "C" {
|
||||
// NB. Mutability can be easily incorrect in FFI calls, as
|
||||
// in C, the default are mutable pointers.
|
||||
fn ffi(c: *mut u8);
|
||||
fn int_ffi(c: *mut i32);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = String::from("Hello");
|
||||
let a = &s;
|
||||
unsafe {
|
||||
let num = &3i32;
|
||||
let mut_num = &mut 3i32;
|
||||
// Should be warned against
|
||||
(*(a as *const _ as *mut String)).push_str(" world");
|
||||
*(a as *const _ as *mut _) = String::from("Replaced");
|
||||
*(a as *const _ as *mut String) += " world";
|
||||
// Shouldn't be warned against
|
||||
println!("{}", *(num as *const _ as *const i16));
|
||||
println!("{}", *(mut_num as *mut _ as *mut i16));
|
||||
ffi(a.as_ptr() as *mut _);
|
||||
int_ffi(num as *const _ as *mut _);
|
||||
int_ffi(&3 as *const _ as *mut _);
|
||||
let mut value = 3;
|
||||
let value: *const i32 = &mut value;
|
||||
*(value as *const i16 as *mut i16) = 42;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell
|
||||
--> $DIR/cast_ref_to_mut.rs:18:9
|
||||
|
|
||||
LL | (*(a as *const _ as *mut String)).push_str(" world");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::cast-ref-to-mut` implied by `-D warnings`
|
||||
|
||||
error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell
|
||||
--> $DIR/cast_ref_to_mut.rs:19:9
|
||||
|
|
||||
LL | *(a as *const _ as *mut _) = String::from("Replaced");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting &T to &mut T may cause undefined behaviour, consider instead using an UnsafeCell
|
||||
--> $DIR/cast_ref_to_mut.rs:20:9
|
||||
|
|
||||
LL | *(a as *const _ as *mut String) += " world";
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
+28
-11
@@ -242,6 +242,34 @@ impl Foo {
|
||||
}
|
||||
}
|
||||
|
||||
mod nesting {
|
||||
struct Foo {}
|
||||
impl Foo {
|
||||
fn foo() {
|
||||
use self::Foo; // Can't use Self here
|
||||
struct Bar {
|
||||
foo: Foo, // Foo != Self
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
fn bar() -> Bar {
|
||||
Bar { foo: Foo {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Enum {
|
||||
A,
|
||||
}
|
||||
impl Enum {
|
||||
fn method() {
|
||||
use self::Enum::*; // Issue 3425
|
||||
static STATIC: Enum = Enum::A; // Can't use Self as type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue3410 {
|
||||
|
||||
struct A;
|
||||
@@ -255,14 +283,3 @@ impl Trait<Vec<A>> for Vec<B> {
|
||||
fn a(_: Vec<A>) {}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue3425 {
|
||||
enum Enum {
|
||||
A,
|
||||
}
|
||||
impl Enum {
|
||||
fn a() {
|
||||
use self::Enum::*;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,5 +150,17 @@ LL | Foo {}
|
||||
LL | use_self_expand!(); // Should lint in local macros
|
||||
| ------------------- in this macro invocation
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:255:29
|
||||
|
|
||||
LL | fn bar() -> Bar {
|
||||
| ^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: unnecessary structure name repetition
|
||||
--> $DIR/use_self.rs:256:21
|
||||
|
|
||||
LL | Bar { foo: Foo {} }
|
||||
| ^^^ help: use the applicable keyword: `Self`
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
||||
Reference in New Issue
Block a user