Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ impl<'hir> LoweringContext<'_, 'hir> {

pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
ensure_sufficient_stack(|| {
let mut span = self.lower_span(e.span);
match &e.kind {
// Parenthesis expression does not have a HirId and is handled specially.
ExprKind::Paren(ex) => {
let mut ex = self.lower_expr_mut(ex);
// Include parens in span, but only if it is a super-span.
if e.span.contains(ex.span) {
ex.span = self.lower_span(e.span);
ex.span = self.lower_span(e.span.with_ctxt(ex.span.ctxt()));
}
// Merge attributes into the inner expression.
if !e.attrs.is_empty() {
Expand Down Expand Up @@ -287,7 +288,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_span(*brackets_span),
),
ExprKind::Range(e1, e2, lims) => {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
self.lower_expr_range(span, e1.as_deref(), e2.as_deref(), *lims)
}
ExprKind::Underscore => {
let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });
Expand Down Expand Up @@ -379,7 +381,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
};

hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
hir::Expr { hir_id: expr_hir_id, kind, span }
})
}

Expand Down Expand Up @@ -1475,7 +1477,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
let e1 = self.lower_expr_mut(e1);
let e2 = self.lower_expr_mut(e2);
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
}
Expand Down Expand Up @@ -1552,14 +1554,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}))
.map(|(s, e)| {
let span = self.lower_span(e.span);
let span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);
let expr = self.lower_expr(e);
let ident = Ident::new(s, self.lower_span(e.span));
self.expr_field(ident, expr, e.span)
let ident = Ident::new(s, span);
self.expr_field(ident, expr, span)
}),
);

hir::ExprKind::Struct(
self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
self.arena.alloc(hir::QPath::LangItem(lang_item, span)),
fields,
hir::StructTailExpr::None,
)
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2457,6 +2457,12 @@ impl Expr<'_> {
}
}

/// If this is a desugared range expression,
/// returns the span of the range without desugaring context.
pub fn range_span(&self) -> Option<Span> {
is_range_literal(self).then(|| self.span.parent_callsite().unwrap())
}

/// Check if expression is an integer literal that can be used
/// where `usize` is expected.
pub fn is_size_lit(&self) -> bool {
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2509,11 +2509,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.tcx
.sess
.source_map()
.span_extend_while_whitespace(range_start.span)
.span_extend_while_whitespace(range_start.expr.span)
.shrink_to_hi()
.to(range_end.span);
.to(range_end.expr.span);

err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr });
err.subdiagnostic(TypeMismatchFruTypo {
expr_span: range_start.expr.span,
fru_span,
expr,
});

// Suppress any range expr type mismatches
self.dcx().try_steal_replace_and_emit_err(
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1666,25 +1666,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match expr.kind {
ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [start, end], _) => {
err.span_suggestion_verbose(
start.span.shrink_to_hi().with_hi(end.span.lo()),
start.expr.span.shrink_to_hi().with_hi(end.expr.span.lo()),
"remove the unnecessary `.` operator for a floating point literal",
'.',
Applicability::MaybeIncorrect,
);
true
}
ExprKind::Struct(QPath::LangItem(LangItem::RangeFrom, ..), [start], _) => {
let range_span = expr.span.parent_callsite().unwrap();
err.span_suggestion_verbose(
expr.span.with_lo(start.span.hi()),
range_span.with_lo(start.expr.span.hi()),
"remove the unnecessary `.` operator for a floating point literal",
'.',
Applicability::MaybeIncorrect,
);
true
}
ExprKind::Struct(QPath::LangItem(LangItem::RangeTo, ..), [end], _) => {
let range_span = expr.span.parent_callsite().unwrap();
err.span_suggestion_verbose(
expr.span.until(end.span),
range_span.until(end.expr.span),
"remove the unnecessary `.` operator and add an integer part for a floating point literal",
"0.",
Applicability::MaybeIncorrect,
Expand Down Expand Up @@ -2693,7 +2695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
bool, /* suggest `&` or `&mut` type annotation */
)> {
let sess = self.sess();
let sp = expr.span;
let sp = expr.range_span().unwrap_or(expr.span);
let sm = sess.source_map();

// If the span is from an external macro, there's no suggestion we can make.
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_lint/src/types/literal.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use hir::{ExprKind, Node, is_range_literal};
use hir::{ExprKind, Node};
use rustc_abi::{Integer, Size};
use rustc_hir::{HirId, attrs};
use rustc_middle::ty::Ty;
Expand Down Expand Up @@ -44,7 +44,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else {
return false;
};
if !is_range_literal(struct_expr) {
let Some(range_span) = struct_expr.range_span() else {
return false;
};
let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else {
Expand All @@ -71,7 +71,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
return false;
};
UseInclusiveRange::WithoutParen {
sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
sugg: range_span.shrink_to_lo().to(lit_span.shrink_to_hi()),
start,
literal: lit_val - 1,
suffix,
Expand All @@ -87,7 +87,7 @@ fn lint_overflowing_range_endpoint<'tcx>(

cx.emit_span_lint(
OVERFLOWING_LITERALS,
struct_expr.span,
range_span,
RangeEndpointOutOfRange { ty, sub: sub_sugg },
);

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,7 @@ pub enum DesugaringKind {
/// rewriting it.
source: bool,
},
RangeExpr,
}

impl DesugaringKind {
Expand All @@ -1268,6 +1269,7 @@ impl DesugaringKind {
DesugaringKind::FormatLiteral { source: false } => {
"expression that expanded into a format string literal"
}
DesugaringKind::RangeExpr => "range expression",
}
}

Expand All @@ -1287,6 +1289,7 @@ impl DesugaringKind {
DesugaringKind::Contract => value == "Contract",
DesugaringKind::PatTyRange => value == "PatTyRange",
DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral",
DesugaringKind::RangeExpr => value == "RangeExpr",
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
expr_needs_parens, is_range_literal,
expr_needs_parens,
};
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_middle::middle::privacy::Level;
Expand Down Expand Up @@ -668,12 +668,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
let derefs = "*".repeat(steps);
let needs_parens = steps > 0
&& match expr.kind {
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
_ if is_range_literal(expr) => true,
_ => false,
};
let needs_parens = steps > 0 && expr_needs_parens(expr);
let mut suggestion = if needs_parens {
vec![
(
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub(super) fn check<'tcx>(
start: Some(start),
end: Some(end),
limits,
span: _,
}) = higher::Range::hir(arg)
// the var must be a single name
&& let PatKind::Binding(_, canonical_id, _, _) = pat.kind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(super) fn check<'tcx>(
start: Some(start),
end: Some(end),
limits: RangeLimits::HalfOpen,
span: _,
}) = higher::Range::hir(arg)
&& let ExprKind::Lit(Spanned {
node: LitKind::Int(Pu128(0), _),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub(super) fn check<'tcx>(
start: Some(start),
ref end,
limits,
span,
}) = higher::Range::hir(arg)
// the var must be a single name
&& let PatKind::Binding(_, canonical_id, ident, _) = pat.kind
Expand Down Expand Up @@ -149,15 +150,15 @@ pub(super) fn check<'tcx>(
span_lint_and_then(
cx,
NEEDLESS_RANGE_LOOP,
arg.span,
span,
format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
|diag| {
diag.multipart_suggestion(
"consider using an iterator and enumerate()",
vec![
(pat.span, format!("({}, <item>)", ident.name)),
(
arg.span,
span,
format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
),
],
Expand All @@ -175,12 +176,12 @@ pub(super) fn check<'tcx>(
span_lint_and_then(
cx,
NEEDLESS_RANGE_LOOP,
arg.span,
span,
format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
|diag| {
diag.multipart_suggestion(
"consider using an iterator",
vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
vec![(pat.span, "<item>".to_string()), (span, repl)],
Applicability::HasPlaceholders,
);
},
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
start: Some(start),
end: Some(end),
limits: RangeLimits::Closed,
span: _,
}) = higher::Range::hir(receiver)
&& !matches!(cx.typeck_results().expr_ty(arg).peel_refs().kind(), ty::Param(_))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal
start: Some(start_expr),
end: None,
limits: ast::RangeLimits::HalfOpen,
span: _,
}) = higher::Range::hir(index_expr)
&& let hir::ExprKind::Lit(start_lit) = &start_expr.kind
&& let ast::LitKind::Int(start_idx, _) = start_lit.node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub(super) fn check(
receiver: &Expr<'_>,
arg: &Expr<'_>,
msrv: Msrv,
method_call_span: Span,
method_name_span: Span,
) {
let mut applicability = Applicability::MaybeIncorrect;
if let Some(range) = higher::Range::hir(receiver)
Expand Down Expand Up @@ -105,7 +105,7 @@ pub(super) fn check(
// collate all our parts here and then remove those that are empty.
let mut parts = vec![
(
receiver.span.to(method_call_span),
ex.span.with_hi(method_name_span.hi()),
format!("{exec_context}::iter::{method_to_use_name}"),
),
new_span,
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4854,8 +4854,8 @@ impl_lint_pass!(Methods => [
/// come from expansion.
pub fn method_call<'tcx>(recv: &'tcx Expr<'tcx>) -> Option<(Symbol, &'tcx Expr<'tcx>, &'tcx [Expr<'tcx>], Span, Span)> {
if let ExprKind::MethodCall(path, receiver, args, call_span) = recv.kind
&& !args.iter().any(|e| e.span.from_expansion())
&& !receiver.span.from_expansion()
&& !args.iter().any(|e| e.range_span().unwrap_or(e.span).from_expansion())
&& !receiver.range_span().unwrap_or(receiver.span).from_expansion()
{
Some((path.ident.name, receiver, args, path.ident.span, call_span))
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/tools/clippy/clippy_lints/src/no_effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl NoEffect {
return true;
}

if expr.span.from_expansion() {
if expr.range_span().unwrap_or(expr.span).from_expansion() {
return false;
}
let expr = peel_blocks(expr);
Expand Down Expand Up @@ -273,7 +273,7 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
if let StmtKind::Semi(expr) = stmt.kind
&& !stmt.span.in_external_macro(cx.sess().source_map())
&& let ctxt = stmt.span.ctxt()
&& expr.span.ctxt() == ctxt
&& expr.range_span().unwrap_or(expr.span).ctxt() == ctxt
&& let Some(reduced) = reduce_expression(cx, expr)
&& reduced.iter().all(|e| e.span.ctxt() == ctxt)
{
Expand Down Expand Up @@ -330,7 +330,7 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
}

fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec<&'a Expr<'a>>> {
if expr.span.from_expansion() {
if expr.range_span().unwrap_or(expr.span).from_expansion() {
return None;
}
match expr.kind {
Expand Down
Loading
Loading