Skip to content

Commit 23fced0

Browse files
committed
Auto merge of #146069 - camsteffen:range-desugar-span, r=SparrowLii
Mark desugared range expression spans with DesugaringKind::RangeExpr This is a prerequisite to removing `QPath::LangItem` (#115178) because otherwise there would be no way to detect a range expression in the HIR. There are some non-obvious Clippy changes so a Clippy team review would be good.
2 parents b1b464d + 6d61dad commit 23fced0

30 files changed

+136
-75
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
6363

6464
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
6565
ensure_sufficient_stack(|| {
66+
let mut span = self.lower_span(e.span);
6667
match &e.kind {
6768
// Parenthesis expression does not have a HirId and is handled specially.
6869
ExprKind::Paren(ex) => {
6970
let mut ex = self.lower_expr_mut(ex);
7071
// Include parens in span, but only if it is a super-span.
7172
if e.span.contains(ex.span) {
72-
ex.span = self.lower_span(e.span);
73+
ex.span = self.lower_span(e.span.with_ctxt(ex.span.ctxt()));
7374
}
7475
// Merge attributes into the inner expression.
7576
if !e.attrs.is_empty() {
@@ -288,7 +289,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
288289
self.lower_span(*brackets_span),
289290
),
290291
ExprKind::Range(e1, e2, lims) => {
291-
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
292+
span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
293+
self.lower_expr_range(span, e1.as_deref(), e2.as_deref(), *lims)
292294
}
293295
ExprKind::Underscore => {
294296
let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });
@@ -380,7 +382,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
380382
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
381383
};
382384

383-
hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
385+
hir::Expr { hir_id: expr_hir_id, kind, span }
384386
})
385387
}
386388

@@ -1482,7 +1484,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14821484
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
14831485
let e1 = self.lower_expr_mut(e1);
14841486
let e2 = self.lower_expr_mut(e2);
1485-
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
1487+
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
14861488
let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
14871489
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
14881490
}
@@ -1559,14 +1561,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
15591561
)
15601562
}))
15611563
.map(|(s, e)| {
1564+
let span = self.lower_span(e.span);
1565+
let span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
15621566
let expr = self.lower_expr(e);
1563-
let ident = Ident::new(s, self.lower_span(e.span));
1564-
self.expr_field(ident, expr, e.span)
1567+
let ident = Ident::new(s, span);
1568+
self.expr_field(ident, expr, span)
15651569
}),
15661570
);
15671571

15681572
hir::ExprKind::Struct(
1569-
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
1573+
self.arena.alloc(hir::QPath::LangItem(lang_item, span)),
15701574
fields,
15711575
hir::StructTailExpr::None,
15721576
)

compiler/rustc_hir/src/hir.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,6 +2460,12 @@ impl Expr<'_> {
24602460
}
24612461
}
24622462

2463+
/// If this is a desugared range expression,
2464+
/// returns the span of the range without desugaring context.
2465+
pub fn range_span(&self) -> Option<Span> {
2466+
is_range_literal(self).then(|| self.span.parent_callsite().unwrap())
2467+
}
2468+
24632469
/// Check if expression is an integer literal that can be used
24642470
/// where `usize` is expected.
24652471
pub fn is_size_lit(&self) -> bool {

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,11 +2509,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25092509
.tcx
25102510
.sess
25112511
.source_map()
2512-
.span_extend_while_whitespace(range_start.span)
2512+
.span_extend_while_whitespace(range_start.expr.span)
25132513
.shrink_to_hi()
2514-
.to(range_end.span);
2514+
.to(range_end.expr.span);
25152515

2516-
err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr });
2516+
err.subdiagnostic(TypeMismatchFruTypo {
2517+
expr_span: range_start.expr.span,
2518+
fru_span,
2519+
expr,
2520+
});
25172521

25182522
// Suppress any range expr type mismatches
25192523
self.dcx().try_steal_replace_and_emit_err(

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,25 +1666,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16661666
match expr.kind {
16671667
ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [start, end], _) => {
16681668
err.span_suggestion_verbose(
1669-
start.span.shrink_to_hi().with_hi(end.span.lo()),
1669+
start.expr.span.shrink_to_hi().with_hi(end.expr.span.lo()),
16701670
"remove the unnecessary `.` operator for a floating point literal",
16711671
'.',
16721672
Applicability::MaybeIncorrect,
16731673
);
16741674
true
16751675
}
16761676
ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, ..), [start], _) => {
1677+
let range_span = expr.span.parent_callsite().unwrap();
16771678
err.span_suggestion_verbose(
1678-
expr.span.with_lo(start.span.hi()),
1679+
range_span.with_lo(start.expr.span.hi()),
16791680
"remove the unnecessary `.` operator for a floating point literal",
16801681
'.',
16811682
Applicability::MaybeIncorrect,
16821683
);
16831684
true
16841685
}
16851686
ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, ..), [end], _) => {
1687+
let range_span = expr.span.parent_callsite().unwrap();
16861688
err.span_suggestion_verbose(
1687-
expr.span.until(end.span),
1689+
range_span.until(end.expr.span),
16881690
"remove the unnecessary `.` operator and add an integer part for a floating point literal",
16891691
"0.",
16901692
Applicability::MaybeIncorrect,
@@ -2693,7 +2695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26932695
bool, /* suggest `&` or `&mut` type annotation */
26942696
)> {
26952697
let sess = self.sess();
2696-
let sp = expr.span;
2698+
let sp = expr.range_span().unwrap_or(expr.span);
26972699
let sm = sess.source_map();
26982700

26992701
// If the span is from an external macro, there's no suggestion we can make.

compiler/rustc_lint/src/types/literal.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use hir::{ExprKind, Node, is_range_literal};
1+
use hir::{ExprKind, Node};
22
use rustc_abi::{Integer, Size};
33
use rustc_hir::{HirId, attrs};
44
use rustc_middle::ty::Ty;
@@ -44,7 +44,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
4444
let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else {
4545
return false;
4646
};
47-
if !is_range_literal(struct_expr) {
47+
let Some(range_span) = struct_expr.range_span() else {
4848
return false;
4949
};
5050
let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else {
@@ -71,7 +71,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
7171
return false;
7272
};
7373
UseInclusiveRange::WithoutParen {
74-
sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
74+
sugg: range_span.shrink_to_lo().to(lit_span.shrink_to_hi()),
7575
start,
7676
literal: lit_val - 1,
7777
suffix,
@@ -87,7 +87,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
8787

8888
cx.emit_span_lint(
8989
OVERFLOWING_LITERALS,
90-
struct_expr.span,
90+
range_span,
9191
RangeEndpointOutOfRange { ty, sub: sub_sugg },
9292
);
9393

compiler/rustc_span/src/hygiene.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,7 @@ pub enum DesugaringKind {
12471247
/// rewriting it.
12481248
source: bool,
12491249
},
1250+
RangeExpr,
12501251
}
12511252

12521253
impl DesugaringKind {
@@ -1268,6 +1269,7 @@ impl DesugaringKind {
12681269
DesugaringKind::FormatLiteral { source: false } => {
12691270
"expression that expanded into a format string literal"
12701271
}
1272+
DesugaringKind::RangeExpr => "range expression",
12711273
}
12721274
}
12731275

@@ -1287,6 +1289,7 @@ impl DesugaringKind {
12871289
DesugaringKind::Contract => value == "Contract",
12881290
DesugaringKind::PatTyRange => value == "PatTyRange",
12891291
DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral",
1292+
DesugaringKind::RangeExpr => value == "RangeExpr",
12901293
}
12911294
}
12921295
}

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt};
2020
use rustc_hir::lang_items::LangItem;
2121
use rustc_hir::{
2222
self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
23-
expr_needs_parens, is_range_literal,
23+
expr_needs_parens,
2424
};
2525
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
2626
use rustc_middle::middle::privacy::Level;
@@ -668,12 +668,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
668668
);
669669
}
670670
let derefs = "*".repeat(steps);
671-
let needs_parens = steps > 0
672-
&& match expr.kind {
673-
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
674-
_ if is_range_literal(expr) => true,
675-
_ => false,
676-
};
671+
let needs_parens = steps > 0 && expr_needs_parens(expr);
677672
let mut suggestion = if needs_parens {
678673
vec![
679674
(

src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub(super) fn check<'tcx>(
2828
start: Some(start),
2929
end: Some(end),
3030
limits,
31+
span: _,
3132
}) = higher::Range::hir(arg)
3233
// the var must be a single name
3334
&& let PatKind::Binding(_, canonical_id, _, _) = pat.kind

src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(super) fn check<'tcx>(
3131
start: Some(start),
3232
end: Some(end),
3333
limits: RangeLimits::HalfOpen,
34+
span: _,
3435
}) = higher::Range::hir(arg)
3536
&& let ExprKind::Lit(Spanned {
3637
node: LitKind::Int(Pu128(0), _),

src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub(super) fn check<'tcx>(
3030
start: Some(start),
3131
ref end,
3232
limits,
33+
span,
3334
}) = higher::Range::hir(arg)
3435
// the var must be a single name
3536
&& let PatKind::Binding(_, canonical_id, ident, _) = pat.kind
@@ -149,15 +150,15 @@ pub(super) fn check<'tcx>(
149150
span_lint_and_then(
150151
cx,
151152
NEEDLESS_RANGE_LOOP,
152-
arg.span,
153+
span,
153154
format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
154155
|diag| {
155156
diag.multipart_suggestion(
156157
"consider using an iterator and enumerate()",
157158
vec![
158159
(pat.span, format!("({}, <item>)", ident.name)),
159160
(
160-
arg.span,
161+
span,
161162
format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
162163
),
163164
],
@@ -175,12 +176,12 @@ pub(super) fn check<'tcx>(
175176
span_lint_and_then(
176177
cx,
177178
NEEDLESS_RANGE_LOOP,
178-
arg.span,
179+
span,
179180
format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
180181
|diag| {
181182
diag.multipart_suggestion(
182183
"consider using an iterator",
183-
vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
184+
vec![(pat.span, "<item>".to_string()), (span, repl)],
184185
Applicability::HasPlaceholders,
185186
);
186187
},

0 commit comments

Comments
 (0)