|
1 | 1 | use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
|
| 2 | +use clippy_utils::higher::Range; |
2 | 3 | use clippy_utils::source::SpanRangeExt;
|
3 | 4 | use clippy_utils::ty::{expr_type_is_certain, has_drop};
|
4 | 5 | use clippy_utils::{
|
@@ -347,6 +348,23 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
|
347 | 348 | ExprKind::Cast(inner, _) if expr_type_is_certain(cx, inner) => {
|
348 | 349 | reduce_expression(cx, inner).or_else(|| Some(vec![inner]))
|
349 | 350 | },
|
| 351 | + // In the normal `Struct` case, we bail out if any of the fields has an uncertain type. |
| 352 | + // But for two-sided ranges, we know that if the type of one of the sides is certain, then so is the other |
| 353 | + // one's. So we only check that, more relaxed pre-condition. |
| 354 | + // |
| 355 | + // Note that that condition true in general for any struct with a generic present in two fields, but |
| 356 | + // generalizing the check to those would be cumbersome. |
| 357 | + ExprKind::Struct(..) |
| 358 | + if let Some(range) = Range::hir(expr) |
| 359 | + && let Some(start) = range.start |
| 360 | + && let Some(end) = range.end => |
| 361 | + { |
| 362 | + if [start, end].into_iter().any(|e| expr_type_is_certain(cx, e)) { |
| 363 | + Some([start, end].into_iter().collect()) |
| 364 | + } else { |
| 365 | + None |
| 366 | + } |
| 367 | + }, |
350 | 368 | ExprKind::Struct(_, fields, ref base) => {
|
351 | 369 | if fields.iter().any(|f| !expr_type_is_certain(cx, &f.expr))
|
352 | 370 | || has_drop(cx, cx.typeck_results().expr_ty(expr))
|
|
0 commit comments