Skip to content

Commit 89a00b0

Browse files
committed
Mark range expr with desugaring
1 parent bd175cb commit 89a00b0

29 files changed

+138
-92
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
}
@@ -1562,15 +1564,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
15621564
let fields = self.arena.alloc_from_iter(
15631565
e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
15641566
|(s, e)| {
1567+
let span = self.lower_span(e.span);
1568+
let span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
15651569
let expr = self.lower_expr(e);
1566-
let ident = Ident::new(s, self.lower_span(e.span));
1567-
self.expr_field(ident, expr, e.span)
1570+
let ident = Ident::new(s, span);
1571+
self.expr_field(ident, expr, span)
15681572
},
15691573
),
15701574
);
15711575

15721576
hir::ExprKind::Struct(
1573-
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
1577+
self.arena.alloc(hir::QPath::LangItem(lang_item, span)),
15741578
fields,
15751579
hir::StructTailExpr::None,
15761580
)

compiler/rustc_hir/src/hir.rs

Lines changed: 11 additions & 25 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;
@@ -2459,6 +2461,12 @@ impl Expr<'_> {
24592461
}
24602462
}
24612463

2464+
/// If this is a desugared range expression,
2465+
/// returns the span of the range without desugaring context.
2466+
pub fn range_span(&self) -> Option<Span> {
2467+
is_range_literal(self).then(|| self.span.parent_callsite().unwrap())
2468+
}
2469+
24622470
/// Check if expression is an integer literal that can be used
24632471
/// where `usize` is expected.
24642472
pub fn is_size_lit(&self) -> bool {
@@ -2694,30 +2702,8 @@ impl Expr<'_> {
26942702
/// Checks if the specified expression is a built-in range literal.
26952703
/// (See: `LoweringContext::lower_expr()`).
26962704
pub fn is_range_literal(expr: &Expr<'_>) -> bool {
2697-
match expr.kind {
2698-
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
2699-
ExprKind::Struct(ref qpath, _, _) => matches!(
2700-
**qpath,
2701-
QPath::LangItem(
2702-
LangItem::Range
2703-
| LangItem::RangeTo
2704-
| LangItem::RangeFrom
2705-
| LangItem::RangeFull
2706-
| LangItem::RangeToInclusive
2707-
| LangItem::RangeCopy
2708-
| LangItem::RangeFromCopy
2709-
| LangItem::RangeInclusiveCopy,
2710-
..
2711-
)
2712-
),
2713-
2714-
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
2715-
ExprKind::Call(ref func, _) => {
2716-
matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
2717-
}
2718-
2719-
_ => false,
2720-
}
2705+
matches!(expr.kind, ExprKind::Call(..) | ExprKind::Struct(..))
2706+
&& expr.span.desugaring_kind() == Some(DesugaringKind::RangeExpr)
27212707
}
27222708

27232709
/// 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
@@ -1600,25 +1600,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16001600
match expr.kind {
16011601
ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [start, end], _) => {
16021602
err.span_suggestion_verbose(
1603-
start.span.shrink_to_hi().with_hi(end.span.lo()),
1603+
start.expr.span.shrink_to_hi().with_hi(end.expr.span.lo()),
16041604
"remove the unnecessary `.` operator for a floating point literal",
16051605
'.',
16061606
Applicability::MaybeIncorrect,
16071607
);
16081608
true
16091609
}
16101610
ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, ..), [start], _) => {
1611+
let range_span = expr.span.parent_callsite().unwrap();
16111612
err.span_suggestion_verbose(
1612-
expr.span.with_lo(start.span.hi()),
1613+
range_span.with_lo(start.expr.span.hi()),
16131614
"remove the unnecessary `.` operator for a floating point literal",
16141615
'.',
16151616
Applicability::MaybeIncorrect,
16161617
);
16171618
true
16181619
}
16191620
ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, ..), [end], _) => {
1621+
let range_span = expr.span.parent_callsite().unwrap();
16201622
err.span_suggestion_verbose(
1621-
expr.span.until(end.span),
1623+
range_span.until(end.expr.span),
16221624
"remove the unnecessary `.` operator and add an integer part for a floating point literal",
16231625
"0.",
16241626
Applicability::MaybeIncorrect,
@@ -2627,7 +2629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26272629
bool, /* suggest `&` or `&mut` type annotation */
26282630
)> {
26292631
let sess = self.sess();
2630-
let sp = expr.span;
2632+
let sp = expr.range_span().unwrap_or(expr.span);
26312633
let sm = sess.source_map();
26322634

26332635
// 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
@@ -108,6 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
108108
start: Some(start),
109109
end: Some(end),
110110
limits: RangeLimits::Closed,
111+
span: _,
111112
}) = higher::Range::hir(receiver)
112113
&& !matches!(cx.typeck_results().expr_ty(arg).peel_refs().kind(), ty::Param(_))
113114
{

0 commit comments

Comments
 (0)