forked from rust-lang/rust-clippy
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32 from TogetherGame/custom_lints_1.74.0
new lint [`invalid_char_range`]
- Loading branch information
Showing
6 changed files
with
248 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use clippy_utils::consts::{constant, Constant}; | ||
use clippy_utils::diagnostics::span_lint_and_note; | ||
use clippy_utils::{def_path_def_ids, is_lint_allowed}; | ||
use rustc_hir::{Expr, ExprKind}; | ||
use rustc_lint::LateContext; | ||
use rustc_span::def_id::DefId; | ||
|
||
use super::INVALID_CHAR_RANGE; | ||
|
||
pub(super) fn check_call(cx: &LateContext<'_>, expr: &Expr<'_>, params: &[Expr<'_>], def_id: DefId) { | ||
if is_lint_allowed(cx, INVALID_CHAR_RANGE, expr.hir_id) || !is_of_from_methods(cx, def_id) { | ||
return; | ||
} | ||
|
||
let [param] = params else { return }; | ||
let param = peel_casts(param); | ||
let tyck_res = cx.typeck_results(); | ||
// Skip checks when input cannot be evaluated at run time. | ||
if let Some(Constant::Int(n)) = constant(cx, tyck_res, param) { | ||
if (n > 0xD7FF && n < 0xE000) || n > 0x0010_FFFF { | ||
span_lint_and_note( | ||
cx, | ||
INVALID_CHAR_RANGE, | ||
expr.span, | ||
"converting to char with out-of-range integer", | ||
Some(param.span), | ||
"this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF]", | ||
); | ||
} | ||
} | ||
} | ||
|
||
fn peel_casts<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { | ||
if let ExprKind::Cast(inner, _) = expr.kind { | ||
peel_casts(inner) | ||
} else { | ||
expr | ||
} | ||
} | ||
|
||
/// Determine if a call's id is either `char::from_u32` or `char::from_u32_unchecked` | ||
fn is_of_from_methods(cx: &LateContext<'_>, def_id: DefId) -> bool { | ||
def_path_def_ids(cx, &["char", "from_u32"]) | ||
.chain(def_path_def_ids(cx, &["char", "from_u32_unchecked"])) | ||
.any(|id| id == def_id) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#![warn(clippy::invalid_char_range)] | ||
|
||
const VALID: u32 = 0xD000; | ||
const INVALID_BETWEEN: u32 = 0xDDDD; | ||
const INVALID_LARGE_SIGNED: i64 = 0xFFFFFF; | ||
|
||
pub fn valid() { | ||
let _ = char::from(97u8); | ||
let _ = char::from_u32(0x10FFFF); | ||
let _ = char::from_u32(VALID); | ||
} | ||
|
||
pub fn invalid() { | ||
let _ = char::from_u32(0xD800); | ||
//~^ ERROR: converting to char with out-of-range integer | ||
//~| NOTE: `-D clippy::invalid-char-range` implied by `-D warnings` | ||
let _ = unsafe { char::from_u32_unchecked(0xD800) }; | ||
//~^ ERROR: converting to char with out-of-range integer | ||
let _ = char::from_u32(INVALID_BETWEEN); | ||
//~^ ERROR: converting to char with out-of-range integer | ||
let _ = char::from_u32(INVALID_BETWEEN + 1); | ||
//~^ ERROR: converting to char with out-of-range integer | ||
let _ = unsafe { char::from_u32_unchecked(INVALID_BETWEEN + 1) }; | ||
//~^ ERROR: converting to char with out-of-range integer | ||
let _ = char::from_u32(INVALID_LARGE_SIGNED as u32); | ||
//~^ ERROR: converting to char with out-of-range integer | ||
let _ = char::from_u32(INVALID_LARGE_SIGNED as usize as u32); | ||
//~^ ERROR: converting to char with out-of-range integer | ||
} | ||
|
||
mod my_char { | ||
pub fn from_u32(u: u32) -> char { | ||
'a' | ||
} | ||
} | ||
|
||
pub fn skip() { | ||
let _ = my_char::from_u32(INVALID_BETWEEN); | ||
} | ||
|
||
fn get_num() -> u32 { | ||
100 | ||
} | ||
// Don't lint uncertain results | ||
pub fn uncertain(n: u32) { | ||
const INVALID_BETWEEN: u32 = 0xDDDD; | ||
let _ = char::from_u32(INVALID_BETWEEN.saturating_sub(1)); | ||
|
||
let _ = char::from_u32(n); | ||
let _ = char::from_u32(10 + n); | ||
let _ = char::from_u32(10_u32.saturating_add(n)); | ||
|
||
let _ = char::from_u32(get_num()); | ||
let clo = || 0; | ||
let _ = char::from_u32(clo()); | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:14:13 | ||
| | ||
LL | let _ = char::from_u32(0xD800); | ||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:14:28 | ||
| | ||
LL | let _ = char::from_u32(0xD800); | ||
| ^^^^^^ | ||
= note: `-D clippy::invalid-char-range` implied by `-D warnings` | ||
= help: to override `-D warnings` add `#[allow(clippy::invalid_char_range)]` | ||
|
||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:17:22 | ||
| | ||
LL | let _ = unsafe { char::from_u32_unchecked(0xD800) }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:17:47 | ||
| | ||
LL | let _ = unsafe { char::from_u32_unchecked(0xD800) }; | ||
| ^^^^^^ | ||
|
||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:19:13 | ||
| | ||
LL | let _ = char::from_u32(INVALID_BETWEEN); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:19:28 | ||
| | ||
LL | let _ = char::from_u32(INVALID_BETWEEN); | ||
| ^^^^^^^^^^^^^^^ | ||
|
||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:21:13 | ||
| | ||
LL | let _ = char::from_u32(INVALID_BETWEEN + 1); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:21:28 | ||
| | ||
LL | let _ = char::from_u32(INVALID_BETWEEN + 1); | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:23:22 | ||
| | ||
LL | let _ = unsafe { char::from_u32_unchecked(INVALID_BETWEEN + 1) }; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:23:47 | ||
| | ||
LL | let _ = unsafe { char::from_u32_unchecked(INVALID_BETWEEN + 1) }; | ||
| ^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:25:13 | ||
| | ||
LL | let _ = char::from_u32(INVALID_LARGE_SIGNED as u32); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:25:28 | ||
| | ||
LL | let _ = char::from_u32(INVALID_LARGE_SIGNED as u32); | ||
| ^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: converting to char with out-of-range integer | ||
--> $DIR/invalid_char_range.rs:27:13 | ||
| | ||
LL | let _ = char::from_u32(INVALID_LARGE_SIGNED as usize as u32); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
note: this number should be within the range of [0, 0xD7FF] or [0xE000, 0x10FFFF] | ||
--> $DIR/invalid_char_range.rs:27:28 | ||
| | ||
LL | let _ = char::from_u32(INVALID_LARGE_SIGNED as usize as u32); | ||
| ^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to 7 previous errors | ||
|