Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check that we don't treat any type but a range type as a range #2735

Merged
merged 1 commit into from
May 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clippy_lints/src/array_indexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
}

// Index is a constant range
if let Some(range) = higher::range(index) {
if let Some(range) = higher::range(cx, index) {
if let Some((start, end)) = to_const_range(cx, range, size) {
if start > size || end > size {
utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds");
Expand All @@ -83,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
}
}

if let Some(range) = higher::range(index) {
if let Some(range) = higher::range(cx, index) {
// Full ranges are always valid
if range.start.is_none() && range.end.is_none() {
return;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/infinite_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness {
} else {
Finite
},
ExprStruct(..) => higher::range(expr)
ExprStruct(..) => higher::range(cx, expr)
.map_or(false, |r| r.end.is_none())
.into(),
_ => Finite,
Expand Down
8 changes: 4 additions & 4 deletions clippy_lints/src/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
start: Some(start),
ref end,
limits,
}) = higher::range(arg)
}) = higher::range(cx, arg)
{
// the var must be a single name
if let PatKind::Binding(_, canonical_id, _, _) = pat.node {
Expand Down Expand Up @@ -982,7 +982,7 @@ fn check_for_loop_range<'a, 'tcx>(
start: Some(start),
ref end,
limits,
}) = higher::range(arg)
}) = higher::range(cx, arg)
{
// the var must be a single name
if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node {
Expand Down Expand Up @@ -1118,7 +1118,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
start: Some(start),
end: Some(end),
limits,
}) = higher::range(arg)
}) = higher::range(cx, arg)
{
// ...and both sides are compile-time constant integers...
if let Some((start_idx, _)) = constant(cx, start) {
Expand Down Expand Up @@ -1456,7 +1456,7 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) {
start: Some(start),
end: Some(end),
..
}) = higher::range(arg)
}) = higher::range(cx, arg)
{
let mut_ids = vec![
check_for_mutability(cx, start),
Expand Down
6 changes: 3 additions & 3 deletions clippy_lints/src/ranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter;
if iter_path.name == "iter";
// range expression in .zip() call: 0..x.len()
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg);
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
if is_integer_literal(start, 0);
// .len() call
if let ExprMethodCall(ref len_path, _, ref len_args) = end.node;
Expand All @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {

// exclusive range plus one: x..(y+1)
if_chain! {
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(expr);
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::HalfOpen }) = higher::range(cx, expr);
if let Some(y) = y_plus_one(end);
then {
span_lint_and_then(
Expand All @@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {

// inclusive range minus one: x..=(y-1)
if_chain! {
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr);
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
if let Some(y) = y_minus_one(end);
then {
span_lint_and_then(
Expand Down
33 changes: 31 additions & 2 deletions clippy_lints/src/utils/higher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#![deny(missing_docs_in_private_items)]

use rustc::hir;
use rustc::{hir, ty};
use rustc::lint::LateContext;
use syntax::ast;
use utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node};
Expand Down Expand Up @@ -44,7 +44,36 @@ pub struct Range<'a> {
}

/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
pub fn range(expr: &hir::Expr) -> Option<Range> {
pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option<Range<'b>> {

let def_path = match cx.tables.expr_ty(expr).sty {
ty::TyAdt(def, _) => cx.tcx.def_path(def.did),
_ => return None,
};

// sanity checks for std::ops::RangeXXXX
if def_path.data.len() != 3 {
return None;
}
if def_path.data.get(0)?.data.as_interned_str() != "ops" {
return None;
}
if def_path.data.get(1)?.data.as_interned_str() != "range" {
return None;
}
let type_name = def_path.data.get(2)?.data.as_interned_str();
let range_types = [
"RangeFrom",
"RangeFull",
"RangeInclusive",
"Range",
"RangeTo",
"RangeToInclusive",
];
if !range_types.contains(&&*type_name.as_str()) {
return None;
}

/// Find the field named `name` in the field. Always return `Some` for
/// convenience.
fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
Expand Down
5 changes: 5 additions & 0 deletions tests/run-pass/ice-2727.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub fn f(new: fn()) {
new();
}

fn main() {}