mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 07:00:55 +00:00
Auto merge of #4839 - flip1995:rollup-new-lints, r=flip1995
Rollup of 4 Pull requests with new lints Rollup of pull requests - #4816 (New lint: zst_offset) - #4814 (New lint: Implement ifs_same_cond_fn) - #4807 (Add `large_stack_arrays` lint) - #4806 (Issue/4623) changelog: add [`zst_offset`] lint changelog: New lint: [`ifs_same_cond_fn`] cahngelog: Add new lint [large_stack_arrays] changelog: added lint [`tabs_in_doc_comments`]
This commit is contained in:
commit
35a559fdd1
19 changed files with 786 additions and 4 deletions
|
@ -1059,6 +1059,7 @@ Released 2018-09-13
|
|||
[`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits
|
||||
[`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_digit_groups
|
||||
[`large_enum_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
|
||||
[`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
|
||||
[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
|
||||
[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
|
||||
[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
|
||||
|
@ -1176,6 +1177,7 @@ Released 2018-09-13
|
|||
[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else
|
||||
[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
|
||||
[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop
|
||||
[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition
|
||||
[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
|
||||
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
|
||||
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
|
||||
|
@ -1201,6 +1203,7 @@ Released 2018-09-13
|
|||
[`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
|
||||
[`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
|
||||
[`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
|
||||
[`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
|
||||
[`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
|
||||
[`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr
|
||||
[`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some
|
||||
|
@ -1273,4 +1276,5 @@ Released 2018-09-13
|
|||
[`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal
|
||||
[`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr
|
||||
[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
|
||||
[`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
|
||||
<!-- end autogenerated links to lint list -->
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
[There are 333 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
[There are 337 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
|
||||
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
|
||||
|
||||
|
|
|
@ -40,6 +40,53 @@ declare_clippy_lint! {
|
|||
"consecutive `ifs` with the same condition"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for consecutive `if`s with the same function call.
|
||||
///
|
||||
/// **Why is this bad?** This is probably a copy & paste error.
|
||||
/// Despite the fact that function can have side effects and `if` works as
|
||||
/// intended, such an approach is implicit and can be considered a "code smell".
|
||||
///
|
||||
/// **Known problems:** Hopefully none.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```ignore
|
||||
/// if foo() == bar {
|
||||
/// …
|
||||
/// } else if foo() == bar {
|
||||
/// …
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This probably should be:
|
||||
/// ```ignore
|
||||
/// if foo() == bar {
|
||||
/// …
|
||||
/// } else if foo() == baz {
|
||||
/// …
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// or if the original code was not a typo and called function mutates a state,
|
||||
/// consider move the mutation out of the `if` condition to avoid similarity to
|
||||
/// a copy & paste error:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let first = foo();
|
||||
/// if first == bar {
|
||||
/// …
|
||||
/// } else {
|
||||
/// let second = foo();
|
||||
/// if second == bar {
|
||||
/// …
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub SAME_FUNCTIONS_IN_IF_CONDITION,
|
||||
pedantic,
|
||||
"consecutive `ifs` with the same function call"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `if/else` with the same body as the *then* part
|
||||
/// and the *else* part.
|
||||
|
@ -102,7 +149,7 @@ declare_clippy_lint! {
|
|||
"`match` with identical arm bodies"
|
||||
}
|
||||
|
||||
declare_lint_pass!(CopyAndPaste => [IFS_SAME_COND, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]);
|
||||
declare_lint_pass!(CopyAndPaste => [IFS_SAME_COND, SAME_FUNCTIONS_IN_IF_CONDITION, IF_SAME_THEN_ELSE, MATCH_SAME_ARMS]);
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
|
@ -119,6 +166,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
|
|||
let (conds, blocks) = if_sequence(expr);
|
||||
lint_same_then_else(cx, &blocks);
|
||||
lint_same_cond(cx, &conds);
|
||||
lint_same_fns_in_if_cond(cx, &conds);
|
||||
lint_match_arms(cx, expr);
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +211,34 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr]) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implementation of `SAME_FUNCTIONS_IN_IF_CONDITION`.
|
||||
fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr]) {
|
||||
let hash: &dyn Fn(&&Expr) -> u64 = &|expr| -> u64 {
|
||||
let mut h = SpanlessHash::new(cx, cx.tables);
|
||||
h.hash_expr(expr);
|
||||
h.finish()
|
||||
};
|
||||
|
||||
let eq: &dyn Fn(&&Expr, &&Expr) -> bool = &|&lhs, &rhs| -> bool {
|
||||
// Do not spawn warning if `IFS_SAME_COND` already produced it.
|
||||
if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) {
|
||||
return false;
|
||||
}
|
||||
SpanlessEq::new(cx).eq_expr(lhs, rhs)
|
||||
};
|
||||
|
||||
for (i, j) in search_same(conds, hash, eq) {
|
||||
span_note_and_lint(
|
||||
cx,
|
||||
SAME_FUNCTIONS_IN_IF_CONDITION,
|
||||
j.span,
|
||||
"this `if` has the same function call as a previous if",
|
||||
i.span,
|
||||
"same as this",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `MATCH_SAME_ARMS`.
|
||||
fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr) {
|
||||
fn same_bindings<'tcx>(
|
||||
|
|
68
clippy_lints/src/large_stack_arrays.rs
Normal file
68
clippy_lints/src/large_stack_arrays.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use rustc::hir::*;
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
use rustc::ty::{self, ConstKind};
|
||||
use rustc::{declare_tool_lint, impl_lint_pass};
|
||||
|
||||
use if_chain::if_chain;
|
||||
|
||||
use crate::rustc_target::abi::LayoutOf;
|
||||
use crate::utils::{snippet, span_help_and_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for local arrays that may be too large.
|
||||
///
|
||||
/// **Why is this bad?** Large local arrays may cause stack overflow.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust,ignore
|
||||
/// let a = [0u32; 1_000_000];
|
||||
/// ```
|
||||
pub LARGE_STACK_ARRAYS,
|
||||
pedantic,
|
||||
"allocating large arrays on stack may cause stack overflow"
|
||||
}
|
||||
|
||||
pub struct LargeStackArrays {
|
||||
maximum_allowed_size: u64,
|
||||
}
|
||||
|
||||
impl LargeStackArrays {
|
||||
#[must_use]
|
||||
pub fn new(maximum_allowed_size: u64) -> Self {
|
||||
Self { maximum_allowed_size }
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]);
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeStackArrays {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
|
||||
if_chain! {
|
||||
if let ExprKind::Repeat(_, _) = expr.kind;
|
||||
if let ty::Array(element_type, cst) = cx.tables.expr_ty(expr).kind;
|
||||
if let ConstKind::Value(val) = cst.val;
|
||||
if let ConstValue::Scalar(element_count) = val;
|
||||
if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
|
||||
if let Ok(element_size) = cx.layout_of(element_type).map(|l| l.size.bytes());
|
||||
if self.maximum_allowed_size < element_count * element_size;
|
||||
then {
|
||||
span_help_and_lint(
|
||||
cx,
|
||||
LARGE_STACK_ARRAYS,
|
||||
expr.span,
|
||||
&format!(
|
||||
"allocating a local array larger than {} bytes",
|
||||
self.maximum_allowed_size
|
||||
),
|
||||
&format!(
|
||||
"consider allocating on the heap with vec!{}.into_boxed_slice()",
|
||||
snippet(cx, expr.span, "[...]")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -212,6 +212,7 @@ pub mod int_plus_one;
|
|||
pub mod integer_division;
|
||||
pub mod items_after_statements;
|
||||
pub mod large_enum_variant;
|
||||
pub mod large_stack_arrays;
|
||||
pub mod len_zero;
|
||||
pub mod let_if_seq;
|
||||
pub mod lifetimes;
|
||||
|
@ -274,6 +275,7 @@ pub mod slow_vector_initialization;
|
|||
pub mod strings;
|
||||
pub mod suspicious_trait_impl;
|
||||
pub mod swap;
|
||||
pub mod tabs_in_doc_comments;
|
||||
pub mod temporary_assignment;
|
||||
pub mod to_digit_is_some;
|
||||
pub mod trait_bounds;
|
||||
|
@ -472,6 +474,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
&copies::IFS_SAME_COND,
|
||||
&copies::IF_SAME_THEN_ELSE,
|
||||
&copies::MATCH_SAME_ARMS,
|
||||
&copies::SAME_FUNCTIONS_IN_IF_CONDITION,
|
||||
©_iterator::COPY_ITERATOR,
|
||||
&dbg_macro::DBG_MACRO,
|
||||
&default_trait_access::DEFAULT_TRAIT_ACCESS,
|
||||
|
@ -538,6 +541,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
&integer_division::INTEGER_DIVISION,
|
||||
&items_after_statements::ITEMS_AFTER_STATEMENTS,
|
||||
&large_enum_variant::LARGE_ENUM_VARIANT,
|
||||
&large_stack_arrays::LARGE_STACK_ARRAYS,
|
||||
&len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||
&len_zero::LEN_ZERO,
|
||||
&let_if_seq::USELESS_LET_IF_SEQ,
|
||||
|
@ -624,6 +628,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
&methods::USELESS_ASREF,
|
||||
&methods::WRONG_PUB_SELF_CONVENTION,
|
||||
&methods::WRONG_SELF_CONVENTION,
|
||||
&methods::ZST_OFFSET,
|
||||
&minmax::MIN_MAX,
|
||||
&misc::CMP_NAN,
|
||||
&misc::CMP_OWNED,
|
||||
|
@ -716,6 +721,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
|
||||
&swap::ALMOST_SWAPPED,
|
||||
&swap::MANUAL_SWAP,
|
||||
&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS,
|
||||
&temporary_assignment::TEMPORARY_ASSIGNMENT,
|
||||
&to_digit_is_some::TO_DIGIT_IS_SOME,
|
||||
&trait_bounds::TYPE_REPETITION_IN_BOUNDS,
|
||||
|
@ -946,10 +952,13 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
|
||||
let enum_variant_name_threshold = conf.enum_variant_name_threshold;
|
||||
store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
|
||||
store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
|
||||
store.register_late_pass(|| box unused_self::UnusedSelf);
|
||||
store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
|
||||
store.register_late_pass(|| box exit::Exit);
|
||||
store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
|
||||
let array_size_threshold = conf.array_size_threshold;
|
||||
store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
|
||||
|
||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
|
||||
|
@ -989,6 +998,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
LintId::of(&attrs::INLINE_ALWAYS),
|
||||
LintId::of(&checked_conversions::CHECKED_CONVERSIONS),
|
||||
LintId::of(&copies::MATCH_SAME_ARMS),
|
||||
LintId::of(&copies::SAME_FUNCTIONS_IN_IF_CONDITION),
|
||||
LintId::of(©_iterator::COPY_ITERATOR),
|
||||
LintId::of(&default_trait_access::DEFAULT_TRAIT_ACCESS),
|
||||
LintId::of(&derive::EXPL_IMPL_CLONE_ON_COPY),
|
||||
|
@ -1003,6 +1013,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
LintId::of(&if_not_else::IF_NOT_ELSE),
|
||||
LintId::of(&infinite_iter::MAYBE_INFINITE_ITER),
|
||||
LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS),
|
||||
LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS),
|
||||
LintId::of(&literal_representation::LARGE_DIGIT_GROUPS),
|
||||
LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP),
|
||||
LintId::of(&loops::EXPLICIT_ITER_LOOP),
|
||||
|
@ -1176,6 +1187,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
LintId::of(&methods::UNNECESSARY_FOLD),
|
||||
LintId::of(&methods::USELESS_ASREF),
|
||||
LintId::of(&methods::WRONG_SELF_CONVENTION),
|
||||
LintId::of(&methods::ZST_OFFSET),
|
||||
LintId::of(&minmax::MIN_MAX),
|
||||
LintId::of(&misc::CMP_NAN),
|
||||
LintId::of(&misc::CMP_OWNED),
|
||||
|
@ -1243,6 +1255,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||
LintId::of(&swap::ALMOST_SWAPPED),
|
||||
LintId::of(&swap::MANUAL_SWAP),
|
||||
LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||
LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT),
|
||||
LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||
LintId::of(&transmute::CROSSPOINTER_TRANSMUTE),
|
||||
|
@ -1370,6 +1383,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
LintId::of(&returns::NEEDLESS_RETURN),
|
||||
LintId::of(&returns::UNUSED_UNIT),
|
||||
LintId::of(&strings::STRING_LIT_AS_BYTES),
|
||||
LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
|
||||
LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
|
||||
LintId::of(&try_err::TRY_ERR),
|
||||
LintId::of(&types::FN_TO_NUMERIC_CAST),
|
||||
|
@ -1497,6 +1511,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
|
|||
LintId::of(&methods::CLONE_DOUBLE_REF),
|
||||
LintId::of(&methods::TEMPORARY_CSTRING_AS_PTR),
|
||||
LintId::of(&methods::UNINIT_ASSUMED_INIT),
|
||||
LintId::of(&methods::ZST_OFFSET),
|
||||
LintId::of(&minmax::MIN_MAX),
|
||||
LintId::of(&misc::CMP_NAN),
|
||||
LintId::of(&misc::FLOAT_CMP),
|
||||
|
|
|
@ -1065,6 +1065,23 @@ declare_clippy_lint! {
|
|||
"`.chcked_add/sub(x).unwrap_or(MAX/MIN)`"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to
|
||||
/// zero-sized types
|
||||
///
|
||||
/// **Why is this bad?** This is a no-op, and likely unintended
|
||||
///
|
||||
/// **Known problems:** None
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```ignore
|
||||
/// unsafe { (&() as *const ()).offest(1) };
|
||||
/// ```
|
||||
pub ZST_OFFSET,
|
||||
correctness,
|
||||
"Check for offset calculations on raw pointers to zero-sized types"
|
||||
}
|
||||
|
||||
declare_lint_pass!(Methods => [
|
||||
OPTION_UNWRAP_USED,
|
||||
RESULT_UNWRAP_USED,
|
||||
|
@ -1109,6 +1126,7 @@ declare_lint_pass!(Methods => [
|
|||
SUSPICIOUS_MAP,
|
||||
UNINIT_ASSUMED_INIT,
|
||||
MANUAL_SATURATING_ARITHMETIC,
|
||||
ZST_OFFSET,
|
||||
]);
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
|
||||
|
@ -1167,6 +1185,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
|
|||
| ["unwrap_or", arith @ "checked_mul"] => {
|
||||
manual_saturating_arithmetic::lint(cx, expr, &arg_lists, &arith["checked_".len()..])
|
||||
},
|
||||
["add"] | ["offset"] | ["sub"] | ["wrapping_offset"] | ["wrapping_add"] | ["wrapping_sub"] => {
|
||||
check_pointer_offset(cx, expr, arg_lists[0])
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
|
@ -3063,3 +3084,15 @@ fn contains_return(expr: &hir::Expr) -> bool {
|
|||
visitor.visit_expr(expr);
|
||||
visitor.found
|
||||
}
|
||||
|
||||
fn check_pointer_offset(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
|
||||
if_chain! {
|
||||
if args.len() == 2;
|
||||
if let ty::RawPtr(ty::TypeAndMut { ref ty, .. }) = cx.tables.expr_ty(&args[0]).kind;
|
||||
if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
|
||||
if layout.is_zst();
|
||||
then {
|
||||
span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
219
clippy_lints/src/tabs_in_doc_comments.rs
Normal file
219
clippy_lints/src/tabs_in_doc_comments.rs
Normal file
|
@ -0,0 +1,219 @@
|
|||
use crate::utils::span_lint_and_sugg;
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
|
||||
use rustc::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_errors::Applicability;
|
||||
use std::convert::TryFrom;
|
||||
use syntax::ast;
|
||||
use syntax::source_map::{BytePos, Span};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks doc comments for usage of tab characters.
|
||||
///
|
||||
/// **Why is this bad?** The rust style-guide promotes spaces instead of tabs for indentation.
|
||||
/// To keep a consistent view on the source, also doc comments should not have tabs.
|
||||
/// Also, explaining ascii-diagrams containing tabs can get displayed incorrectly when the
|
||||
/// display settings of the author and reader differ.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// ///
|
||||
/// /// Struct to hold two strings:
|
||||
/// /// - first one
|
||||
/// /// - second one
|
||||
/// pub struct DoubleString {
|
||||
/// ///
|
||||
/// /// - First String:
|
||||
/// /// - needs to be inside here
|
||||
/// first_string: String,
|
||||
/// ///
|
||||
/// /// - Second String:
|
||||
/// /// - needs to be inside here
|
||||
/// second_string: String,
|
||||
///}
|
||||
/// ```
|
||||
///
|
||||
/// Will be converted to:
|
||||
/// ```rust
|
||||
/// ///
|
||||
/// /// Struct to hold two strings:
|
||||
/// /// - first one
|
||||
/// /// - second one
|
||||
/// pub struct DoubleString {
|
||||
/// ///
|
||||
/// /// - First String:
|
||||
/// /// - needs to be inside here
|
||||
/// first_string: String,
|
||||
/// ///
|
||||
/// /// - Second String:
|
||||
/// /// - needs to be inside here
|
||||
/// second_string: String,
|
||||
///}
|
||||
/// ```
|
||||
pub TABS_IN_DOC_COMMENTS,
|
||||
style,
|
||||
"using tabs in doc comments is not recommended"
|
||||
}
|
||||
|
||||
declare_lint_pass!(TabsInDocComments => [TABS_IN_DOC_COMMENTS]);
|
||||
|
||||
impl TabsInDocComments {
|
||||
fn warn_if_tabs_in_doc(cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||
if let ast::AttrKind::DocComment(comment) = attr.kind {
|
||||
let comment = comment.as_str();
|
||||
|
||||
for (lo, hi) in get_chunks_of_tabs(&comment) {
|
||||
let new_span = Span::new(
|
||||
attr.span.lo() + BytePos(lo),
|
||||
attr.span.lo() + BytePos(hi),
|
||||
attr.span.ctxt(),
|
||||
);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
TABS_IN_DOC_COMMENTS,
|
||||
new_span,
|
||||
"using tabs in doc comments is not recommended",
|
||||
"consider using four spaces per tab",
|
||||
" ".repeat((hi - lo) as usize),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for TabsInDocComments {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attribute: &ast::Attribute) {
|
||||
Self::warn_if_tabs_in_doc(cx, &attribute);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// scans the string for groups of tabs and returns the start(inclusive) and end positions
|
||||
/// (exclusive) of all groups
|
||||
/// e.g. "sd\tasd\t\taa" will be converted to [(2, 3), (6, 8)] as
|
||||
/// 012 3456 7 89
|
||||
/// ^-^ ^---^
|
||||
fn get_chunks_of_tabs(the_str: &str) -> Vec<(u32, u32)> {
|
||||
let line_length_way_to_long = "doc comment longer than 2^32 chars";
|
||||
let mut spans: Vec<(u32, u32)> = vec![];
|
||||
let mut current_start: u32 = 0;
|
||||
|
||||
// tracker to decide if the last group of tabs is not closed by a non-tab character
|
||||
let mut is_active = false;
|
||||
|
||||
let chars_array: Vec<_> = the_str.chars().collect();
|
||||
|
||||
if chars_array == vec!['\t'] {
|
||||
return vec![(0, 1)];
|
||||
}
|
||||
|
||||
for (index, arr) in chars_array.windows(2).enumerate() {
|
||||
let index = u32::try_from(index).expect(line_length_way_to_long);
|
||||
match arr {
|
||||
['\t', '\t'] => {
|
||||
// either string starts with double tab, then we have to set it active,
|
||||
// otherwise is_active is true anyway
|
||||
is_active = true;
|
||||
},
|
||||
[_, '\t'] => {
|
||||
// as ['\t', '\t'] is excluded, this has to be a start of a tab group,
|
||||
// set indices accordingly
|
||||
is_active = true;
|
||||
current_start = index + 1;
|
||||
},
|
||||
['\t', _] => {
|
||||
// this now has to be an end of the group, hence we have to push a new tuple
|
||||
is_active = false;
|
||||
spans.push((current_start, index + 1));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
// only possible when tabs are at the end, insert last group
|
||||
if is_active {
|
||||
spans.push((
|
||||
current_start,
|
||||
u32::try_from(the_str.chars().count()).expect(line_length_way_to_long),
|
||||
));
|
||||
}
|
||||
|
||||
spans
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests_for_get_chunks_of_tabs {
|
||||
use super::get_chunks_of_tabs;
|
||||
|
||||
#[test]
|
||||
fn test_empty_string() {
|
||||
let res = get_chunks_of_tabs("");
|
||||
|
||||
assert_eq!(res, vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple() {
|
||||
let res = get_chunks_of_tabs("sd\t\t\taa");
|
||||
|
||||
assert_eq!(res, vec![(2, 5)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_only_t() {
|
||||
let res = get_chunks_of_tabs("\t\t");
|
||||
|
||||
assert_eq!(res, vec![(0, 2)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_only_one_t() {
|
||||
let res = get_chunks_of_tabs("\t");
|
||||
|
||||
assert_eq!(res, vec![(0, 1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double() {
|
||||
let res = get_chunks_of_tabs("sd\tasd\t\taa");
|
||||
|
||||
assert_eq!(res, vec![(2, 3), (6, 8)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_start() {
|
||||
let res = get_chunks_of_tabs("\t\taa");
|
||||
|
||||
assert_eq!(res, vec![(0, 2)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_end() {
|
||||
let res = get_chunks_of_tabs("aa\t\t");
|
||||
|
||||
assert_eq!(res, vec![(2, 4)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_start_single() {
|
||||
let res = get_chunks_of_tabs("\taa");
|
||||
|
||||
assert_eq!(res, vec![(0, 1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_end_single() {
|
||||
let res = get_chunks_of_tabs("aa\t");
|
||||
|
||||
assert_eq!(res, vec![(2, 3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_tabs() {
|
||||
let res = get_chunks_of_tabs("dsfs");
|
||||
|
||||
assert_eq!(res, vec![]);
|
||||
}
|
||||
}
|
|
@ -151,6 +151,8 @@ define_Conf! {
|
|||
(trivial_copy_size_limit, "trivial_copy_size_limit", None => Option<u64>),
|
||||
/// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have
|
||||
(too_many_lines_threshold, "too_many_lines_threshold", 100 => u64),
|
||||
/// Lint: LARGE_STACK_ARRAYS. The maximum allowed size for arrays on the stack
|
||||
(array_size_threshold, "array_size_threshold", 512_000 => u64),
|
||||
}
|
||||
|
||||
impl Default for Conf {
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use lint::Lint;
|
|||
pub use lint::LINT_LEVELS;
|
||||
|
||||
// begin lint list, do not remove this comment, it’s used in `update_lints`
|
||||
pub const ALL_LINTS: [Lint; 333] = [
|
||||
pub const ALL_LINTS: [Lint; 337] = [
|
||||
Lint {
|
||||
name: "absurd_extreme_comparisons",
|
||||
group: "correctness",
|
||||
|
@ -903,6 +903,13 @@ pub const ALL_LINTS: [Lint; 333] = [
|
|||
deprecation: None,
|
||||
module: "large_enum_variant",
|
||||
},
|
||||
Lint {
|
||||
name: "large_stack_arrays",
|
||||
group: "pedantic",
|
||||
desc: "allocating large arrays on stack may cause stack overflow",
|
||||
deprecation: None,
|
||||
module: "large_stack_arrays",
|
||||
},
|
||||
Lint {
|
||||
name: "len_without_is_empty",
|
||||
group: "style",
|
||||
|
@ -1708,6 +1715,13 @@ pub const ALL_LINTS: [Lint; 333] = [
|
|||
deprecation: None,
|
||||
module: "loops",
|
||||
},
|
||||
Lint {
|
||||
name: "same_functions_in_if_condition",
|
||||
group: "pedantic",
|
||||
desc: "consecutive `ifs` with the same function call",
|
||||
deprecation: None,
|
||||
module: "copies",
|
||||
},
|
||||
Lint {
|
||||
name: "search_is_some",
|
||||
group: "complexity",
|
||||
|
@ -1862,6 +1876,13 @@ pub const ALL_LINTS: [Lint; 333] = [
|
|||
deprecation: None,
|
||||
module: "formatting",
|
||||
},
|
||||
Lint {
|
||||
name: "tabs_in_doc_comments",
|
||||
group: "style",
|
||||
desc: "using tabs in doc comments is not recommended",
|
||||
deprecation: None,
|
||||
module: "tabs_in_doc_comments",
|
||||
},
|
||||
Lint {
|
||||
name: "temporary_assignment",
|
||||
group: "complexity",
|
||||
|
@ -2338,5 +2359,12 @@ pub const ALL_LINTS: [Lint; 333] = [
|
|||
deprecation: None,
|
||||
module: "unicode",
|
||||
},
|
||||
Lint {
|
||||
name: "zst_offset",
|
||||
group: "correctness",
|
||||
desc: "Check for offset calculations on raw pointers to zero-sized types",
|
||||
deprecation: None,
|
||||
module: "methods",
|
||||
},
|
||||
];
|
||||
// end lint list, do not remove this comment, it’s used in `update_lints`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `third-party` at line 5 column 1
|
||||
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `third-party` at line 5 column 1
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
30
tests/ui/large_stack_arrays.rs
Normal file
30
tests/ui/large_stack_arrays.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
#![warn(clippy::large_stack_arrays)]
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct S {
|
||||
pub data: [u64; 32],
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum E {
|
||||
S(S),
|
||||
T(u32),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let bad = (
|
||||
[0u32; 20_000_000],
|
||||
[S { data: [0; 32] }; 5000],
|
||||
[Some(""); 20_000_000],
|
||||
[E::T(0); 5000],
|
||||
);
|
||||
|
||||
let good = (
|
||||
[0u32; 1000],
|
||||
[S { data: [0; 32] }; 1000],
|
||||
[Some(""); 1000],
|
||||
[E::T(0); 1000],
|
||||
[(); 20_000_000],
|
||||
);
|
||||
}
|
35
tests/ui/large_stack_arrays.stderr
Normal file
35
tests/ui/large_stack_arrays.stderr
Normal file
|
@ -0,0 +1,35 @@
|
|||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:17:9
|
||||
|
|
||||
LL | [0u32; 20_000_000],
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::large-stack-arrays` implied by `-D warnings`
|
||||
= help: consider allocating on the heap with vec![0u32; 20_000_000].into_boxed_slice()
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:18:9
|
||||
|
|
||||
LL | [S { data: [0; 32] }; 5000],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with vec![S { data: [0; 32] }; 5000].into_boxed_slice()
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:19:9
|
||||
|
|
||||
LL | [Some(""); 20_000_000],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with vec![Some(""); 20_000_000].into_boxed_slice()
|
||||
|
||||
error: allocating a local array larger than 512000 bytes
|
||||
--> $DIR/large_stack_arrays.rs:20:9
|
||||
|
|
||||
LL | [E::T(0); 5000],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider allocating on the heap with vec![E::T(0); 5000].into_boxed_slice()
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
80
tests/ui/same_functions_in_if_condition.rs
Normal file
80
tests/ui/same_functions_in_if_condition.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
#![warn(clippy::same_functions_in_if_condition)]
|
||||
#![allow(clippy::ifs_same_cond)] // This warning is different from `ifs_same_cond`.
|
||||
#![allow(clippy::if_same_then_else, clippy::comparison_chain)] // all empty blocks
|
||||
|
||||
fn function() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn fn_arg(_arg: u8) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
struct Struct;
|
||||
|
||||
impl Struct {
|
||||
fn method(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn method_arg(&self, _arg: u8) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn ifs_same_cond_fn() {
|
||||
let a = 0;
|
||||
let obj = Struct;
|
||||
|
||||
if function() {
|
||||
} else if function() {
|
||||
//~ ERROR ifs same condition
|
||||
}
|
||||
|
||||
if fn_arg(a) {
|
||||
} else if fn_arg(a) {
|
||||
//~ ERROR ifs same condition
|
||||
}
|
||||
|
||||
if obj.method() {
|
||||
} else if obj.method() {
|
||||
//~ ERROR ifs same condition
|
||||
}
|
||||
|
||||
if obj.method_arg(a) {
|
||||
} else if obj.method_arg(a) {
|
||||
//~ ERROR ifs same condition
|
||||
}
|
||||
|
||||
let mut v = vec![1];
|
||||
if v.pop() == None {
|
||||
//~ ERROR ifs same condition
|
||||
} else if v.pop() == None {
|
||||
}
|
||||
|
||||
if v.len() == 42 {
|
||||
//~ ERROR ifs same condition
|
||||
} else if v.len() == 42 {
|
||||
}
|
||||
|
||||
if v.len() == 1 {
|
||||
// ok, different conditions
|
||||
} else if v.len() == 2 {
|
||||
}
|
||||
|
||||
if fn_arg(0) {
|
||||
// ok, different arguments.
|
||||
} else if fn_arg(1) {
|
||||
}
|
||||
|
||||
if obj.method_arg(0) {
|
||||
// ok, different arguments.
|
||||
} else if obj.method_arg(1) {
|
||||
}
|
||||
|
||||
if a == 1 {
|
||||
// ok, warning is on `ifs_same_cond` behalf.
|
||||
} else if a == 1 {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
75
tests/ui/same_functions_in_if_condition.stderr
Normal file
75
tests/ui/same_functions_in_if_condition.stderr
Normal file
|
@ -0,0 +1,75 @@
|
|||
error: this `if` has the same function call as a previous if
|
||||
--> $DIR/same_functions_in_if_condition.rs:29:15
|
||||
|
|
||||
LL | } else if function() {
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::same-functions-in-if-condition` implied by `-D warnings`
|
||||
note: same as this
|
||||
--> $DIR/same_functions_in_if_condition.rs:28:8
|
||||
|
|
||||
LL | if function() {
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: this `if` has the same function call as a previous if
|
||||
--> $DIR/same_functions_in_if_condition.rs:34:15
|
||||
|
|
||||
LL | } else if fn_arg(a) {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/same_functions_in_if_condition.rs:33:8
|
||||
|
|
||||
LL | if fn_arg(a) {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: this `if` has the same function call as a previous if
|
||||
--> $DIR/same_functions_in_if_condition.rs:39:15
|
||||
|
|
||||
LL | } else if obj.method() {
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/same_functions_in_if_condition.rs:38:8
|
||||
|
|
||||
LL | if obj.method() {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: this `if` has the same function call as a previous if
|
||||
--> $DIR/same_functions_in_if_condition.rs:44:15
|
||||
|
|
||||
LL | } else if obj.method_arg(a) {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/same_functions_in_if_condition.rs:43:8
|
||||
|
|
||||
LL | if obj.method_arg(a) {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this `if` has the same function call as a previous if
|
||||
--> $DIR/same_functions_in_if_condition.rs:51:15
|
||||
|
|
||||
LL | } else if v.pop() == None {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/same_functions_in_if_condition.rs:49:8
|
||||
|
|
||||
LL | if v.pop() == None {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: this `if` has the same function call as a previous if
|
||||
--> $DIR/same_functions_in_if_condition.rs:56:15
|
||||
|
|
||||
LL | } else if v.len() == 42 {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: same as this
|
||||
--> $DIR/same_functions_in_if_condition.rs:54:8
|
||||
|
|
||||
LL | if v.len() == 42 {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
22
tests/ui/tabs_in_doc_comments.fixed
Normal file
22
tests/ui/tabs_in_doc_comments.fixed
Normal file
|
@ -0,0 +1,22 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::tabs_in_doc_comments)]
|
||||
#[allow(dead_code)]
|
||||
|
||||
///
|
||||
/// Struct to hold two strings:
|
||||
/// - first one
|
||||
/// - second one
|
||||
pub struct DoubleString {
|
||||
///
|
||||
/// - First String:
|
||||
/// - needs to be inside here
|
||||
first_string: String,
|
||||
///
|
||||
/// - Second String:
|
||||
/// - needs to be inside here
|
||||
second_string: String,
|
||||
}
|
||||
|
||||
/// This is main
|
||||
fn main() {}
|
22
tests/ui/tabs_in_doc_comments.rs
Normal file
22
tests/ui/tabs_in_doc_comments.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::tabs_in_doc_comments)]
|
||||
#[allow(dead_code)]
|
||||
|
||||
///
|
||||
/// Struct to hold two strings:
|
||||
/// - first one
|
||||
/// - second one
|
||||
pub struct DoubleString {
|
||||
///
|
||||
/// - First String:
|
||||
/// - needs to be inside here
|
||||
first_string: String,
|
||||
///
|
||||
/// - Second String:
|
||||
/// - needs to be inside here
|
||||
second_string: String,
|
||||
}
|
||||
|
||||
/// This is main
|
||||
fn main() {}
|
52
tests/ui/tabs_in_doc_comments.stderr
Normal file
52
tests/ui/tabs_in_doc_comments.stderr
Normal file
|
@ -0,0 +1,52 @@
|
|||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:12:9
|
||||
|
|
||||
LL | /// - First String:
|
||||
| ^^^^ help: consider using four spaces per tab
|
||||
|
|
||||
= note: `-D clippy::tabs-in-doc-comments` implied by `-D warnings`
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:13:9
|
||||
|
|
||||
LL | /// - needs to be inside here
|
||||
| ^^^^^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:16:9
|
||||
|
|
||||
LL | /// - Second String:
|
||||
| ^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:17:9
|
||||
|
|
||||
LL | /// - needs to be inside here
|
||||
| ^^^^^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:8:5
|
||||
|
|
||||
LL | /// - first one
|
||||
| ^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:8:13
|
||||
|
|
||||
LL | /// - first one
|
||||
| ^^^^^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:9:5
|
||||
|
|
||||
LL | /// - second one
|
||||
| ^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: using tabs in doc comments is not recommended
|
||||
--> $DIR/tabs_in_doc_comments.rs:9:14
|
||||
|
|
||||
LL | /// - second one
|
||||
| ^^^^ help: consider using four spaces per tab
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
12
tests/ui/zero_offset.rs
Normal file
12
tests/ui/zero_offset.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
fn main() {
|
||||
unsafe {
|
||||
let x = &() as *const ();
|
||||
x.offset(0);
|
||||
x.wrapping_add(0);
|
||||
x.sub(0);
|
||||
x.wrapping_sub(0);
|
||||
|
||||
let y = &1 as *const u8;
|
||||
y.offset(0);
|
||||
}
|
||||
}
|
9
tests/ui/zero_offset.stderr
Normal file
9
tests/ui/zero_offset.stderr
Normal file
|
@ -0,0 +1,9 @@
|
|||
error[E0606]: casting `&i32` as `*const u8` is invalid
|
||||
--> $DIR/zero_offset.rs:9:17
|
||||
|
|
||||
LL | let y = &1 as *const u8;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0606`.
|
Loading…
Reference in a new issue