Skip to content

Commit be3cba8

Browse files
authored
Merge pull request #2735 from rust-lang-nursery/ice_melting
Check that we don't treat any type but a range type as a range
2 parents b39d541 + c6e35ea commit be3cba8

File tree

6 files changed

+46
-12
lines changed

6 files changed

+46
-12
lines changed

clippy_lints/src/array_indexing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
7373
}
7474

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

86-
if let Some(range) = higher::range(index) {
86+
if let Some(range) = higher::range(cx, index) {
8787
// Full ranges are always valid
8888
if range.start.is_none() && range.end.is_none() {
8989
return;

clippy_lints/src/infinite_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ fn is_infinite(cx: &LateContext, expr: &Expr) -> Finiteness {
167167
} else {
168168
Finite
169169
},
170-
ExprStruct(..) => higher::range(expr)
170+
ExprStruct(..) => higher::range(cx, expr)
171171
.map_or(false, |r| r.end.is_none())
172172
.into(),
173173
_ => Finite,

clippy_lints/src/loops.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
888888
start: Some(start),
889889
ref end,
890890
limits,
891-
}) = higher::range(arg)
891+
}) = higher::range(cx, arg)
892892
{
893893
// the var must be a single name
894894
if let PatKind::Binding(_, canonical_id, _, _) = pat.node {
@@ -982,7 +982,7 @@ fn check_for_loop_range<'a, 'tcx>(
982982
start: Some(start),
983983
ref end,
984984
limits,
985-
}) = higher::range(arg)
985+
}) = higher::range(cx, arg)
986986
{
987987
// the var must be a single name
988988
if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node {
@@ -1118,7 +1118,7 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
11181118
start: Some(start),
11191119
end: Some(end),
11201120
limits,
1121-
}) = higher::range(arg)
1121+
}) = higher::range(cx, arg)
11221122
{
11231123
// ...and both sides are compile-time constant integers...
11241124
if let Some((start_idx, _)) = constant(cx, start) {
@@ -1456,7 +1456,7 @@ fn check_for_mut_range_bound(cx: &LateContext, arg: &Expr, body: &Expr) {
14561456
start: Some(start),
14571457
end: Some(end),
14581458
..
1459-
}) = higher::range(arg)
1459+
}) = higher::range(cx, arg)
14601460
{
14611461
let mut_ids = vec![
14621462
check_for_mutability(cx, start),

clippy_lints/src/ranges.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
110110
if let ExprMethodCall(ref iter_path, _, ref iter_args ) = *iter;
111111
if iter_path.name == "iter";
112112
// range expression in .zip() call: 0..x.len()
113-
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg);
113+
if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
114114
if is_integer_literal(start, 0);
115115
// .len() call
116116
if let ExprMethodCall(ref len_path, _, ref len_args) = end.node;
@@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
132132

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

154154
// inclusive range minus one: x..=(y-1)
155155
if_chain! {
156-
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(expr);
156+
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::range(cx, expr);
157157
if let Some(y) = y_minus_one(end);
158158
then {
159159
span_lint_and_then(

clippy_lints/src/utils/higher.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
#![deny(missing_docs_in_private_items)]
55

6-
use rustc::hir;
6+
use rustc::{hir, ty};
77
use rustc::lint::LateContext;
88
use syntax::ast;
99
use utils::{is_expn_of, match_def_path, match_qpath, opt_def_id, paths, resolve_node};
@@ -44,7 +44,36 @@ pub struct Range<'a> {
4444
}
4545

4646
/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
47-
pub fn range(expr: &hir::Expr) -> Option<Range> {
47+
pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> Option<Range<'b>> {
48+
49+
let def_path = match cx.tables.expr_ty(expr).sty {
50+
ty::TyAdt(def, _) => cx.tcx.def_path(def.did),
51+
_ => return None,
52+
};
53+
54+
// sanity checks for std::ops::RangeXXXX
55+
if def_path.data.len() != 3 {
56+
return None;
57+
}
58+
if def_path.data.get(0)?.data.as_interned_str() != "ops" {
59+
return None;
60+
}
61+
if def_path.data.get(1)?.data.as_interned_str() != "range" {
62+
return None;
63+
}
64+
let type_name = def_path.data.get(2)?.data.as_interned_str();
65+
let range_types = [
66+
"RangeFrom",
67+
"RangeFull",
68+
"RangeInclusive",
69+
"Range",
70+
"RangeTo",
71+
"RangeToInclusive",
72+
];
73+
if !range_types.contains(&&*type_name.as_str()) {
74+
return None;
75+
}
76+
4877
/// Find the field named `name` in the field. Always return `Some` for
4978
/// convenience.
5079
fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {

tests/run-pass/ice-2727.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub fn f(new: fn()) {
2+
new();
3+
}
4+
5+
fn main() {}

0 commit comments

Comments
 (0)