Skip to content

Commit c252165

Browse files
committed
Mark range expr with desugaring
1 parent 30e358d commit c252165

29 files changed

+138
-93
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
6262

6363
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
6464
ensure_sufficient_stack(|| {
65+
let mut span = self.lower_span(e.span);
6566
match &e.kind {
6667
// Parenthesis expression does not have a HirId and is handled specially.
6768
ExprKind::Paren(ex) => {
@@ -287,7 +288,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
287288
self.lower_span(*brackets_span),
288289
),
289290
ExprKind::Range(e1, e2, lims) => {
290-
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
291+
span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
292+
self.lower_expr_range(span, e1.as_deref(), e2.as_deref(), *lims)
291293
}
292294
ExprKind::Underscore => {
293295
let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });
@@ -379,7 +381,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
379381
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
380382
};
381383

382-
hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
384+
hir::Expr { hir_id: expr_hir_id, kind, span }
383385
})
384386
}
385387

@@ -1505,7 +1507,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15051507
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
15061508
let e1 = self.lower_expr_mut(e1);
15071509
let e2 = self.lower_expr_mut(e2);
1508-
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
1510+
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
15091511
let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
15101512
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
15111513
}
@@ -1582,14 +1584,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
15821584
)
15831585
}))
15841586
.map(|(s, e)| {
1587+
let span = self.lower_span(e.span);
1588+
let span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
15851589
let expr = self.lower_expr(e);
1586-
let ident = Ident::new(s, self.lower_span(e.span));
1587-
self.expr_field(ident, expr, e.span)
1590+
let ident = Ident::new(s, span);
1591+
self.expr_field(ident, expr, span)
15881592
}),
15891593
);
15901594

15911595
hir::ExprKind::Struct(
1592-
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
1596+
self.arena.alloc(hir::QPath::LangItem(lang_item, span)),
15931597
fields,
15941598
hir::StructTailExpr::None,
15951599
)

compiler/rustc_hir/src/hir.rs

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ use rustc_index::IndexVec;
2323
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
2424
use rustc_span::def_id::LocalDefId;
2525
use rustc_span::source_map::Spanned;
26-
use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
26+
use rustc_span::{
27+
BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, Span, Symbol, kw, sym,
28+
};
2729
use rustc_target::asm::InlineAsmRegOrRegClass;
2830
use smallvec::SmallVec;
2931
use thin_vec::ThinVec;
@@ -2458,6 +2460,12 @@ impl Expr<'_> {
24582460
}
24592461
}
24602462

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+
24612469
/// Check if expression is an integer literal that can be used
24622470
/// where `usize` is expected.
24632471
pub fn is_size_lit(&self) -> bool {
@@ -2705,31 +2713,8 @@ impl Expr<'_> {
27052713
/// Checks if the specified expression is a built-in range literal.
27062714
/// (See: `LoweringContext::lower_expr()`).
27072715
pub fn is_range_literal(expr: &Expr<'_>) -> bool {
2708-
match expr.kind {
2709-
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
2710-
ExprKind::Struct(ref qpath, _, _) => matches!(
2711-
**qpath,
2712-
QPath::LangItem(
2713-
LangItem::Range
2714-
| LangItem::RangeTo
2715-
| LangItem::RangeFrom
2716-
| LangItem::RangeFull
2717-
| LangItem::RangeToInclusive
2718-
| LangItem::RangeCopy
2719-
| LangItem::RangeFromCopy
2720-
| LangItem::RangeInclusiveCopy
2721-
| LangItem::RangeToInclusiveCopy,
2722-
..
2723-
)
2724-
),
2725-
2726-
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
2727-
ExprKind::Call(ref func, _) => {
2728-
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
2729-
}
2730-
2731-
_ => false,
2732-
}
2716+
matches!(expr.kind, ExprKind::Call(..) | ExprKind::Struct(..))
2717+
&& expr.span.desugaring_kind() == Some(DesugaringKind::RangeExpr)
27332718
}
27342719

27352720
/// Checks if the specified expression needs parentheses for prefix

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,11 +2500,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25002500
.tcx
25012501
.sess
25022502
.source_map()
2503-
.span_extend_while_whitespace(range_start.span)
2503+
.span_extend_while_whitespace(range_start.expr.span)
25042504
.shrink_to_hi()
2505-
.to(range_end.span);
2505+
.to(range_end.expr.span);
25062506

2507-
err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr });
2507+
err.subdiagnostic(TypeMismatchFruTypo {
2508+
expr_span: range_start.expr.span,
2509+
fru_span,
2510+
expr,
2511+
});
25082512

25092513
// Suppress any range expr type mismatches
25102514
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
@@ -1237,6 +1237,7 @@ pub enum DesugaringKind {
12371237
/// rewriting it.
12381238
source: bool,
12391239
},
1240+
RangeExpr,
12401241
}
12411242

12421243
impl DesugaringKind {
@@ -1258,6 +1259,7 @@ impl DesugaringKind {
12581259
DesugaringKind::FormatLiteral { source: false } => {
12591260
"expression that expanded into a format string literal"
12601261
}
1262+
DesugaringKind::RangeExpr => "range expression",
12611263
}
12621264
}
12631265

@@ -1277,6 +1279,7 @@ impl DesugaringKind {
12771279
DesugaringKind::Contract => value == "Contract",
12781280
DesugaringKind::PatTyRange => value == "PatTyRange",
12791281
DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral",
1282+
DesugaringKind::RangeExpr => value == "RangeExpr",
12801283
}
12811284
}
12821285
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(super) fn check<'tcx>(
2727
start: Some(start),
2828
end: Some(end),
2929
limits,
30+
span: _,
3031
}) = higher::Range::hir(arg)
3132
// the var must be a single name
3233
&& 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
},

src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
109109
start: Some(start),
110110
end: Some(end),
111111
limits: RangeLimits::Closed,
112+
span: _,
112113
}) = higher::Range::hir(receiver)
113114
&& !matches!(cx.typeck_results().expr_ty(arg).peel_refs().kind(), ty::Param(_))
114115
{

0 commit comments

Comments
 (0)