Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a2af9cf

Browse files
committedMar 16, 2022
Auto merge of #94987 - Dylan-DPC:rollup-5tssuhi, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #94868 (Format core and std macro rules, removing needless surrounding blocks) - #94951 (Extend the irrefutable_let_patterns lint to let chains) - #94955 (Refactor: Use `format_args_capture` in some parts of `rustc_parse`) - #94957 (Improve the explanation about the behaviour of read_line) - #94974 (Ensure that `let_else` does not interact with `let_chains`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents af446e1 + aaf2255 commit a2af9cf

File tree

19 files changed

+650
-151
lines changed

19 files changed

+650
-151
lines changed
 

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 180 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
158158
self.check_patterns(pat, Refutable);
159159
let mut cx = self.new_cx(scrutinee.hir_id);
160160
let tpat = self.lower_pattern(&mut cx, pat, &mut false);
161-
check_let_reachability(&mut cx, pat.hir_id, tpat, span);
161+
self.check_let_reachability(&mut cx, pat.hir_id, tpat, span);
162162
}
163163

164164
fn check_match(
@@ -176,7 +176,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
176176
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
177177
self.check_patterns(pat, Refutable);
178178
let tpat = self.lower_pattern(&mut cx, pat, &mut false);
179-
check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span());
179+
self.check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span());
180180
}
181181
}
182182

@@ -224,6 +224,157 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
224224
}
225225
}
226226

227+
fn check_let_reachability(
228+
&mut self,
229+
cx: &mut MatchCheckCtxt<'p, 'tcx>,
230+
pat_id: HirId,
231+
pat: &'p DeconstructedPat<'p, 'tcx>,
232+
span: Span,
233+
) {
234+
if self.check_let_chain(cx, pat_id) {
235+
return;
236+
}
237+
238+
if is_let_irrefutable(cx, pat_id, pat) {
239+
irrefutable_let_pattern(cx.tcx, pat_id, span);
240+
}
241+
}
242+
243+
fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId) -> bool {
244+
let hir = self.tcx.hir();
245+
let parent = hir.get_parent_node(pat_id);
246+
247+
// First, figure out if the given pattern is part of a let chain,
248+
// and if so, obtain the top node of the chain.
249+
let mut top = parent;
250+
let mut part_of_chain = false;
251+
loop {
252+
let new_top = hir.get_parent_node(top);
253+
if let hir::Node::Expr(
254+
hir::Expr {
255+
kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs),
256+
..
257+
},
258+
..,
259+
) = hir.get(new_top)
260+
{
261+
// If this isn't the first iteration, we need to check
262+
// if there is a let expr before us in the chain, so
263+
// that we avoid doubly checking the let chain.
264+
265+
// The way a chain of &&s is encoded is ((let ... && let ...) && let ...) && let ...
266+
// as && is left-to-right associative. Thus, we need to check rhs.
267+
if part_of_chain && matches!(rhs.kind, hir::ExprKind::Let(..)) {
268+
return true;
269+
}
270+
// If there is a let at the lhs, and we provide the rhs, we don't do any checking either.
271+
if !part_of_chain && matches!(lhs.kind, hir::ExprKind::Let(..)) && rhs.hir_id == top
272+
{
273+
return true;
274+
}
275+
} else {
276+
// We've reached the top.
277+
break;
278+
}
279+
280+
// Since this function is called within a let context, it is reasonable to assume that any parent
281+
// `&&` infers a let chain
282+
part_of_chain = true;
283+
top = new_top;
284+
}
285+
if !part_of_chain {
286+
return false;
287+
}
288+
289+
// Second, obtain the refutabilities of all exprs in the chain,
290+
// and record chain members that aren't let exprs.
291+
let mut chain_refutabilities = Vec::new();
292+
let hir::Node::Expr(top_expr) = hir.get(top) else {
293+
// We ensure right above that it's an Expr
294+
unreachable!()
295+
};
296+
let mut cur_expr = top_expr;
297+
loop {
298+
let mut add = |expr: &hir::Expr<'tcx>| {
299+
let refutability = match expr.kind {
300+
hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => {
301+
let mut ncx = self.new_cx(init.hir_id);
302+
let tpat = self.lower_pattern(&mut ncx, pat, &mut false);
303+
304+
let refutable = !is_let_irrefutable(&mut ncx, pat.hir_id, tpat);
305+
Some((*span, refutable))
306+
}
307+
_ => None,
308+
};
309+
chain_refutabilities.push(refutability);
310+
};
311+
if let hir::Expr {
312+
kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs),
313+
..
314+
} = cur_expr
315+
{
316+
add(rhs);
317+
cur_expr = lhs;
318+
} else {
319+
add(cur_expr);
320+
break;
321+
}
322+
}
323+
chain_refutabilities.reverse();
324+
325+
// Third, emit the actual warnings.
326+
327+
if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) {
328+
// The entire chain is made up of irrefutable `let` statements
329+
let let_source = let_source_parent(self.tcx, top, None);
330+
irrefutable_let_patterns(
331+
cx.tcx,
332+
top,
333+
let_source,
334+
chain_refutabilities.len(),
335+
top_expr.span,
336+
);
337+
return true;
338+
}
339+
let lint_affix = |affix: &[Option<(Span, bool)>], kind, suggestion| {
340+
let span_start = affix[0].unwrap().0;
341+
let span_end = affix.last().unwrap().unwrap().0;
342+
let span = span_start.to(span_end);
343+
let cnt = affix.len();
344+
cx.tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, top, span, |lint| {
345+
let s = pluralize!(cnt);
346+
let mut diag = lint.build(&format!("{kind} irrefutable pattern{s} in let chain"));
347+
diag.note(&format!(
348+
"{these} pattern{s} will always match",
349+
these = pluralize!("this", cnt),
350+
));
351+
diag.help(&format!(
352+
"consider moving {} {suggestion}",
353+
if cnt > 1 { "them" } else { "it" }
354+
));
355+
diag.emit()
356+
});
357+
};
358+
if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
359+
// The chain has a non-zero prefix of irrefutable `let` statements.
360+
361+
// Check if the let source is while, for there is no alternative place to put a prefix,
362+
// and we shouldn't lint.
363+
let let_source = let_source_parent(self.tcx, top, None);
364+
if !matches!(let_source, LetSource::WhileLet) {
365+
// Emit the lint
366+
let prefix = &chain_refutabilities[..until];
367+
lint_affix(prefix, "leading", "outside of the construct");
368+
}
369+
}
370+
if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) {
371+
// The chain has a non-empty suffix of irrefutable `let` statements
372+
let suffix = &chain_refutabilities[from + 1..];
373+
lint_affix(suffix, "trailing", "into the body");
374+
}
375+
true
376+
}
377+
227378
fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>) {
228379
let mut cx = self.new_cx(pat.hir_id);
229380

@@ -453,21 +604,33 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<
453604
}
454605

455606
fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
607+
let source = let_source(tcx, id);
608+
irrefutable_let_patterns(tcx, id, source, 1, span);
609+
}
610+
611+
fn irrefutable_let_patterns(
612+
tcx: TyCtxt<'_>,
613+
id: HirId,
614+
source: LetSource,
615+
count: usize,
616+
span: Span,
617+
) {
456618
macro_rules! emit_diag {
457619
(
458620
$lint:expr,
459621
$source_name:expr,
460622
$note_sufix:expr,
461623
$help_sufix:expr
462624
) => {{
463-
let mut diag = $lint.build(concat!("irrefutable ", $source_name, " pattern"));
464-
diag.note(concat!("this pattern will always match, so the ", $note_sufix));
625+
let s = pluralize!(count);
626+
let these = pluralize!("this", count);
627+
let mut diag = $lint.build(&format!("irrefutable {} pattern{s}", $source_name));
628+
diag.note(&format!("{these} pattern{s} will always match, so the {}", $note_sufix));
465629
diag.help(concat!("consider ", $help_sufix));
466630
diag.emit()
467631
}};
468632
}
469633

470-
let source = let_source(tcx, id);
471634
let span = match source {
472635
LetSource::LetElse(span) => span,
473636
_ => span,
@@ -511,16 +674,11 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
511674
});
512675
}
513676

514-
fn check_let_reachability<'p, 'tcx>(
677+
fn is_let_irrefutable<'p, 'tcx>(
515678
cx: &mut MatchCheckCtxt<'p, 'tcx>,
516679
pat_id: HirId,
517680
pat: &'p DeconstructedPat<'p, 'tcx>,
518-
span: Span,
519-
) {
520-
if is_let_chain(cx.tcx, pat_id) {
521-
return;
522-
}
523-
681+
) -> bool {
524682
let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }];
525683
let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty());
526684

@@ -529,10 +687,9 @@ fn check_let_reachability<'p, 'tcx>(
529687
// `is_uninhabited` check.
530688
report_arm_reachability(&cx, &report);
531689

532-
if report.non_exhaustiveness_witnesses.is_empty() {
533-
// The match is exhaustive, i.e. the `if let` pattern is irrefutable.
534-
irrefutable_let_pattern(cx.tcx, pat_id, span);
535-
}
690+
// If the list of witnesses is empty, the match is exhaustive,
691+
// i.e. the `if let` pattern is irrefutable.
692+
report.non_exhaustiveness_witnesses.is_empty()
536693
}
537694

538695
/// Report unreachable arms, if any.
@@ -941,13 +1098,19 @@ fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
9411098
let hir = tcx.hir();
9421099

9431100
let parent = hir.get_parent_node(pat_id);
1101+
let_source_parent(tcx, parent, Some(pat_id))
1102+
}
1103+
1104+
fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> LetSource {
1105+
let hir = tcx.hir();
1106+
9441107
let parent_node = hir.get(parent);
9451108

9461109
match parent_node {
9471110
hir::Node::Arm(hir::Arm {
9481111
guard: Some(hir::Guard::IfLet(&hir::Pat { hir_id, .. }, _)),
9491112
..
950-
}) if hir_id == pat_id => {
1113+
}) if Some(hir_id) == pat_id => {
9511114
return LetSource::IfLetGuard;
9521115
}
9531116
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {
@@ -980,21 +1143,3 @@ fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
9801143

9811144
LetSource::GenericLet
9821145
}
983-
984-
// Since this function is called within a let context, it is reasonable to assume that any parent
985-
// `&&` infers a let chain
986-
fn is_let_chain(tcx: TyCtxt<'_>, pat_id: HirId) -> bool {
987-
let hir = tcx.hir();
988-
let parent = hir.get_parent_node(pat_id);
989-
let parent_parent = hir.get_parent_node(parent);
990-
matches!(
991-
hir.get(parent_parent),
992-
hir::Node::Expr(
993-
hir::Expr {
994-
kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, ..),
995-
..
996-
},
997-
..
998-
)
999-
)
1000-
}

‎compiler/rustc_parse/src/parser/attr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl<'a> Parser<'a> {
139139
Ok(attr::mk_attr_from_item(item, None, style, attr_sp))
140140
} else {
141141
let token_str = pprust::token_to_string(&this.token);
142-
let msg = &format!("expected `#`, found `{}`", token_str);
142+
let msg = &format!("expected `#`, found `{token_str}`");
143143
Err(this.struct_span_err(this.token.span, msg))
144144
}
145145
})
@@ -421,7 +421,7 @@ impl<'a> Parser<'a> {
421421
}
422422

423423
let found = pprust::token_to_string(&self.token);
424-
let msg = format!("expected unsuffixed literal or identifier, found `{}`", found);
424+
let msg = format!("expected unsuffixed literal or identifier, found `{found}`");
425425
Err(self.struct_span_err(self.token.span, &msg))
426426
}
427427
}

‎compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,8 @@ impl<'a> Parser<'a> {
327327
expect.clone()
328328
};
329329
(
330-
format!("expected one of {}, found {}", expect, actual),
331-
(self.prev_token.span.shrink_to_hi(), format!("expected one of {}", short_expect)),
330+
format!("expected one of {expect}, found {actual}"),
331+
(self.prev_token.span.shrink_to_hi(), format!("expected one of {short_expect}")),
332332
)
333333
} else if expected.is_empty() {
334334
(
@@ -337,8 +337,8 @@ impl<'a> Parser<'a> {
337337
)
338338
} else {
339339
(
340-
format!("expected {}, found {}", expect, actual),
341-
(self.prev_token.span.shrink_to_hi(), format!("expected {}", expect)),
340+
format!("expected {expect}, found {actual}"),
341+
(self.prev_token.span.shrink_to_hi(), format!("expected {expect}")),
342342
)
343343
};
344344
self.last_unexpected_token_span = Some(self.token.span);
@@ -421,7 +421,7 @@ impl<'a> Parser<'a> {
421421
String::new(),
422422
Applicability::MachineApplicable,
423423
);
424-
err.note(&format!("the raw string started with {} `#`s", n_hashes));
424+
err.note(&format!("the raw string started with {n_hashes} `#`s"));
425425
true
426426
}
427427
_ => false,
@@ -1191,7 +1191,7 @@ impl<'a> Parser<'a> {
11911191
_ => None,
11921192
};
11931193
if let Some(name) = previous_item_kind_name {
1194-
err.help(&format!("{} declarations are not followed by a semicolon", name));
1194+
err.help(&format!("{name} declarations are not followed by a semicolon"));
11951195
}
11961196
}
11971197
err.emit();
@@ -1226,12 +1226,12 @@ impl<'a> Parser<'a> {
12261226
"expected `{}`, found {}",
12271227
token_str,
12281228
match (&self.token.kind, self.subparser_name) {
1229-
(token::Eof, Some(origin)) => format!("end of {}", origin),
1229+
(token::Eof, Some(origin)) => format!("end of {origin}"),
12301230
_ => this_token_str,
12311231
},
12321232
);
12331233
let mut err = self.struct_span_err(sp, &msg);
1234-
let label_exp = format!("expected `{}`", token_str);
1234+
let label_exp = format!("expected `{token_str}`");
12351235
match self.recover_closing_delimiter(&[t.clone()], err) {
12361236
Err(e) => err = e,
12371237
Ok(recovered) => {
@@ -1368,7 +1368,7 @@ impl<'a> Parser<'a> {
13681368
Applicability::MachineApplicable,
13691369
);
13701370
}
1371-
err.span_suggestion(lo.shrink_to_lo(), &format!("{}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax", prefix), "r#".to_string(), Applicability::MachineApplicable);
1371+
err.span_suggestion(lo.shrink_to_lo(), &format!("{prefix}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax"), "r#".to_string(), Applicability::MachineApplicable);
13721372
err.emit();
13731373
Ok(self.mk_expr_err(lo.to(hi)))
13741374
} else {
@@ -1504,7 +1504,7 @@ impl<'a> Parser<'a> {
15041504
delim.retain(|c| c != '`');
15051505
err.span_suggestion_short(
15061506
self.prev_token.span.shrink_to_hi(),
1507-
&format!("`{}` may belong here", delim),
1507+
&format!("`{delim}` may belong here"),
15081508
delim,
15091509
Applicability::MaybeIncorrect,
15101510
);
@@ -1698,7 +1698,7 @@ impl<'a> Parser<'a> {
16981698
(
16991699
ident,
17001700
"self: ".to_string(),
1701-
format!("{}: &{}TypeName", ident, mutab),
1701+
format!("{ident}: &{mutab}TypeName"),
17021702
"_: ".to_string(),
17031703
pat.span.shrink_to_lo(),
17041704
pat.span,
@@ -1826,7 +1826,7 @@ impl<'a> Parser<'a> {
18261826
let (span, msg) = match (&self.token.kind, self.subparser_name) {
18271827
(&token::Eof, Some(origin)) => {
18281828
let sp = self.sess.source_map().next_point(self.prev_token.span);
1829-
(sp, format!("expected expression, found end of {}", origin))
1829+
(sp, format!("expected expression, found end of {origin}"))
18301830
}
18311831
_ => (
18321832
self.token.span,
@@ -1975,8 +1975,8 @@ impl<'a> Parser<'a> {
19751975
(ty_generics, self.sess.source_map().span_to_snippet(param.span()))
19761976
{
19771977
let (span, sugg) = match &generics.params[..] {
1978-
[] => (generics.span, format!("<{}>", snippet)),
1979-
[.., generic] => (generic.span().shrink_to_hi(), format!(", {}", snippet)),
1978+
[] => (generics.span, format!("<{snippet}>")),
1979+
[.., generic] => (generic.span().shrink_to_hi(), format!(", {snippet}")),
19801980
};
19811981
err.multipart_suggestion(
19821982
"`const` parameters must be declared for the `impl`",

‎compiler/rustc_parse/src/parser/expr.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ impl<'a> Parser<'a> {
223223
AssocOp::NotEqual => "!=",
224224
_ => unreachable!(),
225225
};
226-
self.struct_span_err(sp, &format!("invalid comparison operator `{}=`", sugg))
226+
self.struct_span_err(sp, &format!("invalid comparison operator `{sugg}=`"))
227227
.span_suggestion_short(
228228
sp,
229229
&format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg),
@@ -441,10 +441,10 @@ impl<'a> Parser<'a> {
441441

442442
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
443443
fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
444-
self.struct_span_err(self.token.span, &format!("`{}` is not a logical operator", bad))
444+
self.struct_span_err(self.token.span, &format!("`{bad}` is not a logical operator"))
445445
.span_suggestion_short(
446446
self.token.span,
447-
&format!("use `{}` to perform logical {}", good, english),
447+
&format!("use `{good}` to perform logical {english}"),
448448
good.to_string(),
449449
Applicability::MachineApplicable,
450450
)
@@ -766,9 +766,9 @@ impl<'a> Parser<'a> {
766766
self.look_ahead(1, |t| t.span).to(span_after_type),
767767
"interpreted as generic arguments",
768768
)
769-
.span_label(self.token.span, format!("not interpreted as {}", op_noun))
769+
.span_label(self.token.span, format!("not interpreted as {op_noun}"))
770770
.multipart_suggestion(
771-
&format!("try {} the cast value", op_verb),
771+
&format!("try {op_verb} the cast value"),
772772
vec![
773773
(expr.span.shrink_to_lo(), "(".to_string()),
774774
(expr.span.shrink_to_hi(), ")".to_string()),
@@ -970,7 +970,7 @@ impl<'a> Parser<'a> {
970970
fn error_unexpected_after_dot(&self) {
971971
// FIXME Could factor this out into non_fatal_unexpected or something.
972972
let actual = pprust::token_to_string(&self.token);
973-
self.struct_span_err(self.token.span, &format!("unexpected token: `{}`", actual)).emit();
973+
self.struct_span_err(self.token.span, &format!("unexpected token: `{actual}`")).emit();
974974
}
975975

976976
// We need an identifier or integer, but the next token is a float.
@@ -1151,15 +1151,15 @@ impl<'a> Parser<'a> {
11511151
mem::replace(err, replacement_err).cancel();
11521152

11531153
err.multipart_suggestion(
1154-
&format!("if `{}` is a struct, use braces as delimiters", name),
1154+
&format!("if `{name}` is a struct, use braces as delimiters"),
11551155
vec![
11561156
(open_paren, " { ".to_string()),
11571157
(close_paren, " }".to_string()),
11581158
],
11591159
Applicability::MaybeIncorrect,
11601160
);
11611161
err.multipart_suggestion(
1162-
&format!("if `{}` is a function, use the arguments directly", name),
1162+
&format!("if `{name}` is a function, use the arguments directly"),
11631163
fields
11641164
.into_iter()
11651165
.map(|field| (field.span.until(field.expr.span), String::new()))
@@ -1776,9 +1776,9 @@ impl<'a> Parser<'a> {
17761776
)
17771777
.emit();
17781778
} else {
1779-
let msg = format!("invalid suffix `{}` for number literal", suf);
1779+
let msg = format!("invalid suffix `{suf}` for number literal");
17801780
self.struct_span_err(span, &msg)
1781-
.span_label(span, format!("invalid suffix `{}`", suf))
1781+
.span_label(span, format!("invalid suffix `{suf}`"))
17821782
.help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")
17831783
.emit();
17841784
}
@@ -1791,9 +1791,9 @@ impl<'a> Parser<'a> {
17911791
let msg = format!("invalid width `{}` for float literal", &suf[1..]);
17921792
self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit();
17931793
} else {
1794-
let msg = format!("invalid suffix `{}` for float literal", suf);
1794+
let msg = format!("invalid suffix `{suf}` for float literal");
17951795
self.struct_span_err(span, &msg)
1796-
.span_label(span, format!("invalid suffix `{}`", suf))
1796+
.span_label(span, format!("invalid suffix `{suf}`"))
17971797
.help("valid suffixes are `f32` and `f64`")
17981798
.emit();
17991799
}
@@ -1805,7 +1805,7 @@ impl<'a> Parser<'a> {
18051805
2 => "binary",
18061806
_ => unreachable!(),
18071807
};
1808-
self.struct_span_err(span, &format!("{} float literal is not supported", descr))
1808+
self.struct_span_err(span, &format!("{descr} float literal is not supported"))
18091809
.span_label(span, "not supported")
18101810
.emit();
18111811
}
@@ -1825,7 +1825,7 @@ impl<'a> Parser<'a> {
18251825
let mut err = self
18261826
.sess
18271827
.span_diagnostic
1828-
.struct_span_warn(sp, &format!("suffixes on {} are invalid", kind));
1828+
.struct_span_warn(sp, &format!("suffixes on {kind} are invalid"));
18291829
err.note(&format!(
18301830
"`{}` is *temporarily* accepted on tuple index fields as it was \
18311831
incorrectly accepted on stable for a few releases",
@@ -1842,10 +1842,10 @@ impl<'a> Parser<'a> {
18421842
);
18431843
err
18441844
} else {
1845-
self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
1845+
self.struct_span_err(sp, &format!("suffixes on {kind} are invalid"))
18461846
.forget_guarantee()
18471847
};
1848-
err.span_label(sp, format!("invalid suffix `{}`", suf));
1848+
err.span_label(sp, format!("invalid suffix `{suf}`"));
18491849
err.emit();
18501850
}
18511851
}
@@ -2211,7 +2211,7 @@ impl<'a> Parser<'a> {
22112211
let ctx = if is_ctx_else { "else" } else { "if" };
22122212
self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
22132213
.span_label(branch_span, "the attributes are attached to this branch")
2214-
.span_label(ctx_span, format!("the branch belongs to this `{}`", ctx))
2214+
.span_label(ctx_span, format!("the branch belongs to this `{ctx}`"))
22152215
.span_suggestion(
22162216
span,
22172217
"remove the attributes",
@@ -2391,7 +2391,7 @@ impl<'a> Parser<'a> {
23912391
err.span_label(arrow_span, "while parsing the `match` arm starting here");
23922392
if stmts.len() > 1 {
23932393
err.multipart_suggestion(
2394-
&format!("surround the statement{} with a body", s),
2394+
&format!("surround the statement{s} with a body"),
23952395
vec![
23962396
(span.shrink_to_lo(), "{ ".to_string()),
23972397
(span.shrink_to_hi(), " }".to_string()),

‎compiler/rustc_parse/src/parser/item.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl<'a> Parser<'a> {
6666
if !self.eat(term) {
6767
let token_str = super::token_descr(&self.token);
6868
if !self.maybe_consume_incorrect_semicolon(&items) {
69-
let msg = &format!("expected item, found {}", token_str);
69+
let msg = &format!("expected item, found {token_str}");
7070
let mut err = self.struct_span_err(self.token.span, msg);
7171
err.span_label(self.token.span, "expected item");
7272
return Err(err);
@@ -163,9 +163,9 @@ impl<'a> Parser<'a> {
163163
}
164164
let vs = pprust::vis_to_string(&vis);
165165
let vs = vs.trim_end();
166-
self.struct_span_err(vis.span, &format!("visibility `{}` is not followed by an item", vs))
166+
self.struct_span_err(vis.span, &format!("visibility `{vs}` is not followed by an item"))
167167
.span_label(vis.span, "the visibility")
168-
.help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs))
168+
.help(&format!("you likely meant to define an item, e.g., `{vs} fn foo() {{}}`"))
169169
.emit();
170170
}
171171

@@ -327,7 +327,7 @@ impl<'a> Parser<'a> {
327327
if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) {
328328
// possible public struct definition where `struct` was forgotten
329329
let ident = self.parse_ident().unwrap();
330-
let msg = format!("add `struct` here to parse `{}` as a public struct", ident);
330+
let msg = format!("add `struct` here to parse `{ident}` as a public struct");
331331
let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
332332
err.span_suggestion_short(
333333
sp,
@@ -355,16 +355,16 @@ impl<'a> Parser<'a> {
355355
("fn` or `struct", "function or struct", true)
356356
};
357357

358-
let msg = format!("missing `{}` for {} definition", kw, kw_name);
358+
let msg = format!("missing `{kw}` for {kw_name} definition");
359359
let mut err = self.struct_span_err(sp, &msg);
360360
if !ambiguous {
361361
self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
362362
let suggestion =
363-
format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name);
363+
format!("add `{kw}` here to parse `{ident}` as a public {kw_name}");
364364
err.span_suggestion_short(
365365
sp,
366366
&suggestion,
367-
format!(" {} ", kw),
367+
format!(" {kw} "),
368368
Applicability::MachineApplicable,
369369
);
370370
} else if let Ok(snippet) = self.span_to_snippet(ident_sp) {
@@ -393,12 +393,12 @@ impl<'a> Parser<'a> {
393393
} else {
394394
("fn` or `struct", "function or struct", true)
395395
};
396-
let msg = format!("missing `{}` for {} definition", kw, kw_name);
396+
let msg = format!("missing `{kw}` for {kw_name} definition");
397397
let mut err = self.struct_span_err(sp, &msg);
398398
if !ambiguous {
399399
err.span_suggestion_short(
400400
sp,
401-
&format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name),
401+
&format!("add `{kw}` here to parse `{ident}` as a public {kw_name}"),
402402
format!(" {} ", kw),
403403
Applicability::MachineApplicable,
404404
);
@@ -1031,8 +1031,8 @@ impl<'a> Parser<'a> {
10311031
fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
10321032
let span = self.sess.source_map().guess_head_span(span);
10331033
let descr = kind.descr();
1034-
self.struct_span_err(span, &format!("{} is not supported in {}", descr, ctx))
1035-
.help(&format!("consider moving the {} out to a nearby module scope", descr))
1034+
self.struct_span_err(span, &format!("{descr} is not supported in {ctx}"))
1035+
.help(&format!("consider moving the {descr} out to a nearby module scope"))
10361036
.emit();
10371037
None
10381038
}
@@ -1161,11 +1161,11 @@ impl<'a> Parser<'a> {
11611161
Some(Mutability::Not) => "static",
11621162
None => "const",
11631163
};
1164-
let mut err = self.struct_span_err(id.span, &format!("missing type for `{}` item", kind));
1164+
let mut err = self.struct_span_err(id.span, &format!("missing type for `{kind}` item"));
11651165
err.span_suggestion(
11661166
id.span,
11671167
"provide a type for the item",
1168-
format!("{}: <type>", id),
1168+
format!("{id}: <type>"),
11691169
Applicability::HasPlaceholders,
11701170
);
11711171
err.stash(id.span, StashKey::ItemNoType);
@@ -1282,8 +1282,7 @@ impl<'a> Parser<'a> {
12821282
} else {
12831283
let token_str = super::token_descr(&self.token);
12841284
let msg = &format!(
1285-
"expected `where`, `{{`, `(`, or `;` after struct name, found {}",
1286-
token_str
1285+
"expected `where`, `{{`, `(`, or `;` after struct name, found {token_str}"
12871286
);
12881287
let mut err = self.struct_span_err(self.token.span, msg);
12891288
err.span_label(self.token.span, "expected `where`, `{`, `(`, or `;` after struct name");
@@ -1310,7 +1309,7 @@ impl<'a> Parser<'a> {
13101309
VariantData::Struct(fields, recovered)
13111310
} else {
13121311
let token_str = super::token_descr(&self.token);
1313-
let msg = &format!("expected `where` or `{{` after union name, found {}", token_str);
1312+
let msg = &format!("expected `where` or `{{` after union name, found {token_str}");
13141313
let mut err = self.struct_span_err(self.token.span, msg);
13151314
err.span_label(self.token.span, "expected `where` or `{` after union name");
13161315
return Err(err);
@@ -1591,7 +1590,7 @@ impl<'a> Parser<'a> {
15911590
}
15921591
let mut err = self.struct_span_err(
15931592
lo.to(self.prev_token.span),
1594-
&format!("functions are not allowed in {} definitions", adt_ty),
1593+
&format!("functions are not allowed in {adt_ty} definitions"),
15951594
);
15961595
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
15971596
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
@@ -1706,7 +1705,7 @@ impl<'a> Parser<'a> {
17061705
let vstr = pprust::vis_to_string(vis);
17071706
let vstr = vstr.trim_end();
17081707
if macro_rules {
1709-
let msg = format!("can't qualify macro_rules invocation with `{}`", vstr);
1708+
let msg = format!("can't qualify macro_rules invocation with `{vstr}`");
17101709
self.struct_span_err(vis.span, &msg)
17111710
.span_suggestion(
17121711
vis.span,
@@ -1723,7 +1722,7 @@ impl<'a> Parser<'a> {
17231722
String::new(),
17241723
Applicability::MachineApplicable,
17251724
)
1726-
.help(&format!("try adjusting the macro to put `{}` inside the invocation", vstr))
1725+
.help(&format!("try adjusting the macro to put `{vstr}` inside the invocation"))
17271726
.emit();
17281727
}
17291728
}
@@ -1781,11 +1780,11 @@ impl<'a> Parser<'a> {
17811780

17821781
self.struct_span_err(
17831782
kw_token.span,
1784-
&format!("`{}` definition cannot be nested inside `{}`", kw_str, keyword),
1783+
&format!("`{kw_str}` definition cannot be nested inside `{keyword}`"),
17851784
)
17861785
.span_suggestion(
17871786
item.unwrap().span,
1788-
&format!("consider creating a new `{}` definition instead of nesting", kw_str),
1787+
&format!("consider creating a new `{kw_str}` definition instead of nesting"),
17891788
String::new(),
17901789
Applicability::MaybeIncorrect,
17911790
)
@@ -2045,11 +2044,11 @@ impl<'a> Parser<'a> {
20452044

20462045
err.span_suggestion(
20472046
self.token.uninterpolated_span(),
2048-
&format!("`{}` already used earlier, remove this one", original_kw),
2047+
&format!("`{original_kw}` already used earlier, remove this one"),
20492048
"".to_string(),
20502049
Applicability::MachineApplicable,
20512050
)
2052-
.span_note(original_sp, &format!("`{}` first seen here", original_kw));
2051+
.span_note(original_sp, &format!("`{original_kw}` first seen here"));
20532052
}
20542053
// The keyword has not been seen yet, suggest correct placement in the function front matter
20552054
else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
@@ -2060,8 +2059,8 @@ impl<'a> Parser<'a> {
20602059

20612060
err.span_suggestion(
20622061
correct_pos_sp.to(misplaced_qual_sp),
2063-
&format!("`{}` must come before `{}`", misplaced_qual, current_qual),
2064-
format!("{} {}", misplaced_qual, current_qual),
2062+
&format!("`{misplaced_qual}` must come before `{current_qual}`"),
2063+
format!("{misplaced_qual} {current_qual}"),
20652064
Applicability::MachineApplicable,
20662065
).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`");
20672066
}
@@ -2084,8 +2083,8 @@ impl<'a> Parser<'a> {
20842083
if matches!(orig_vis.kind, VisibilityKind::Inherited) {
20852084
err.span_suggestion(
20862085
sp_start.to(self.prev_token.span),
2087-
&format!("visibility `{}` must come before `{}`", vs, snippet),
2088-
format!("{} {}", vs, snippet),
2086+
&format!("visibility `{vs}` must come before `{snippet}`"),
2087+
format!("{vs} {snippet}"),
20892088
Applicability::MachineApplicable,
20902089
);
20912090
}

‎library/core/src/macros/mod.rs

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ macro_rules! panic {
3434
#[cfg_attr(not(test), rustc_diagnostic_item = "assert_eq_macro")]
3535
#[allow_internal_unstable(core_panic)]
3636
macro_rules! assert_eq {
37-
($left:expr, $right:expr $(,)?) => ({
37+
($left:expr, $right:expr $(,)?) => {
3838
match (&$left, &$right) {
3939
(left_val, right_val) => {
4040
if !(*left_val == *right_val) {
@@ -46,8 +46,8 @@ macro_rules! assert_eq {
4646
}
4747
}
4848
}
49-
});
50-
($left:expr, $right:expr, $($arg:tt)+) => ({
49+
};
50+
($left:expr, $right:expr, $($arg:tt)+) => {
5151
match (&$left, &$right) {
5252
(left_val, right_val) => {
5353
if !(*left_val == *right_val) {
@@ -59,7 +59,7 @@ macro_rules! assert_eq {
5959
}
6060
}
6161
}
62-
});
62+
};
6363
}
6464

6565
/// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
@@ -84,7 +84,7 @@ macro_rules! assert_eq {
8484
#[cfg_attr(not(test), rustc_diagnostic_item = "assert_ne_macro")]
8585
#[allow_internal_unstable(core_panic)]
8686
macro_rules! assert_ne {
87-
($left:expr, $right:expr $(,)?) => ({
87+
($left:expr, $right:expr $(,)?) => {
8888
match (&$left, &$right) {
8989
(left_val, right_val) => {
9090
if *left_val == *right_val {
@@ -96,8 +96,8 @@ macro_rules! assert_ne {
9696
}
9797
}
9898
}
99-
});
100-
($left:expr, $right:expr, $($arg:tt)+) => ({
99+
};
100+
($left:expr, $right:expr, $($arg:tt)+) => {
101101
match (&($left), &($right)) {
102102
(left_val, right_val) => {
103103
if *left_val == *right_val {
@@ -109,7 +109,7 @@ macro_rules! assert_ne {
109109
}
110110
}
111111
}
112-
});
112+
};
113113
}
114114

115115
/// Asserts that an expression matches any of the given patterns.
@@ -142,7 +142,7 @@ macro_rules! assert_ne {
142142
#[allow_internal_unstable(core_panic)]
143143
#[rustc_macro_transparency = "semitransparent"]
144144
pub macro assert_matches {
145-
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => ({
145+
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
146146
match $left {
147147
$( $pattern )|+ $( if $guard )? => {}
148148
ref left_val => {
@@ -153,8 +153,8 @@ pub macro assert_matches {
153153
);
154154
}
155155
}
156-
}),
157-
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => ({
156+
},
157+
($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {
158158
match $left {
159159
$( $pattern )|+ $( if $guard )? => {}
160160
ref left_val => {
@@ -165,7 +165,7 @@ pub macro assert_matches {
165165
);
166166
}
167167
}
168-
}),
168+
},
169169
}
170170

171171
/// Asserts that a boolean expression is `true` at runtime.
@@ -214,7 +214,11 @@ pub macro assert_matches {
214214
#[rustc_diagnostic_item = "debug_assert_macro"]
215215
#[allow_internal_unstable(edition_panic)]
216216
macro_rules! debug_assert {
217-
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
217+
($($arg:tt)*) => {
218+
if $crate::cfg!(debug_assertions) {
219+
$crate::assert!($($arg)*);
220+
}
221+
};
218222
}
219223

220224
/// Asserts that two expressions are equal to each other.
@@ -240,7 +244,11 @@ macro_rules! debug_assert {
240244
#[stable(feature = "rust1", since = "1.0.0")]
241245
#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_eq_macro")]
242246
macro_rules! debug_assert_eq {
243-
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
247+
($($arg:tt)*) => {
248+
if $crate::cfg!(debug_assertions) {
249+
$crate::assert_eq!($($arg)*);
250+
}
251+
};
244252
}
245253

246254
/// Asserts that two expressions are not equal to each other.
@@ -266,7 +274,11 @@ macro_rules! debug_assert_eq {
266274
#[stable(feature = "assert_ne", since = "1.13.0")]
267275
#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_ne_macro")]
268276
macro_rules! debug_assert_ne {
269-
($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
277+
($($arg:tt)*) => {
278+
if $crate::cfg!(debug_assertions) {
279+
$crate::assert_ne!($($arg)*);
280+
}
281+
};
270282
}
271283

272284
/// Asserts that an expression matches any of the given patterns.
@@ -305,7 +317,9 @@ macro_rules! debug_assert_ne {
305317
#[allow_internal_unstable(assert_matches)]
306318
#[rustc_macro_transparency = "semitransparent"]
307319
pub macro debug_assert_matches($($arg:tt)*) {
308-
if $crate::cfg!(debug_assertions) { $crate::assert_matches::assert_matches!($($arg)*); }
320+
if $crate::cfg!(debug_assertions) {
321+
$crate::assert_matches::assert_matches!($($arg)*);
322+
}
309323
}
310324

311325
/// Returns whether the given expression matches any of the given patterns.
@@ -331,7 +345,7 @@ macro_rules! matches {
331345
$( $pattern )|+ $( if $guard )? => true,
332346
_ => false
333347
}
334-
}
348+
};
335349
}
336350

337351
/// Unwraps a result or propagates its error.
@@ -482,7 +496,9 @@ macro_rules! r#try {
482496
#[stable(feature = "rust1", since = "1.0.0")]
483497
#[cfg_attr(not(test), rustc_diagnostic_item = "write_macro")]
484498
macro_rules! write {
485-
($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
499+
($dst:expr, $($arg:tt)*) => {
500+
$dst.write_fmt($crate::format_args!($($arg)*))
501+
};
486502
}
487503

488504
/// Write formatted data into a buffer, with a newline appended.
@@ -534,12 +550,12 @@ macro_rules! write {
534550
#[cfg_attr(not(test), rustc_diagnostic_item = "writeln_macro")]
535551
#[allow_internal_unstable(format_args_nl)]
536552
macro_rules! writeln {
537-
($dst:expr $(,)?) => (
553+
($dst:expr $(,)?) => {
538554
$crate::write!($dst, "\n")
539-
);
540-
($dst:expr, $($arg:tt)*) => (
555+
};
556+
($dst:expr, $($arg:tt)*) => {
541557
$dst.write_fmt($crate::format_args_nl!($($arg)*))
542-
);
558+
};
543559
}
544560

545561
/// Indicates unreachable code.
@@ -683,8 +699,12 @@ macro_rules! unreachable {
683699
#[cfg_attr(not(test), rustc_diagnostic_item = "unimplemented_macro")]
684700
#[allow_internal_unstable(core_panic)]
685701
macro_rules! unimplemented {
686-
() => ($crate::panicking::panic("not implemented"));
687-
($($arg:tt)+) => ($crate::panic!("not implemented: {}", $crate::format_args!($($arg)+)));
702+
() => {
703+
$crate::panicking::panic("not implemented")
704+
};
705+
($($arg:tt)+) => {
706+
$crate::panic!("not implemented: {}", $crate::format_args!($($arg)+))
707+
};
688708
}
689709

690710
/// Indicates unfinished code.
@@ -746,8 +766,12 @@ macro_rules! unimplemented {
746766
#[cfg_attr(not(test), rustc_diagnostic_item = "todo_macro")]
747767
#[allow_internal_unstable(core_panic)]
748768
macro_rules! todo {
749-
() => ($crate::panicking::panic("not yet implemented"));
750-
($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
769+
() => {
770+
$crate::panicking::panic("not yet implemented")
771+
};
772+
($($arg:tt)+) => {
773+
$crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+))
774+
};
751775
}
752776

753777
/// Definitions of built-in macros.

‎library/std/src/io/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2110,7 +2110,8 @@ pub trait BufRead: Read {
21102110
}
21112111

21122112
/// Read all bytes until a newline (the `0xA` byte) is reached, and append
2113-
/// them to the provided buffer.
2113+
/// them to the provided buffer. You do not need to clear the buffer before
2114+
/// appending.
21142115
///
21152116
/// This function will read bytes from the underlying stream until the
21162117
/// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes

‎library/std/src/macros.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ macro_rules! panic {
6060
#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")]
6161
#[allow_internal_unstable(print_internals)]
6262
macro_rules! print {
63-
($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
63+
($($arg:tt)*) => {
64+
$crate::io::_print($crate::format_args!($($arg)*))
65+
};
6466
}
6567

6668
/// Prints to the standard output, with a newline.
@@ -94,10 +96,12 @@ macro_rules! print {
9496
#[cfg_attr(not(test), rustc_diagnostic_item = "println_macro")]
9597
#[allow_internal_unstable(print_internals, format_args_nl)]
9698
macro_rules! println {
97-
() => ($crate::print!("\n"));
98-
($($arg:tt)*) => ({
99-
$crate::io::_print($crate::format_args_nl!($($arg)*));
100-
})
99+
() => {
100+
$crate::print!("\n")
101+
};
102+
($($arg:tt)*) => {
103+
$crate::io::_print($crate::format_args_nl!($($arg)*))
104+
};
101105
}
102106

103107
/// Prints to the standard error.
@@ -126,7 +130,9 @@ macro_rules! println {
126130
#[cfg_attr(not(test), rustc_diagnostic_item = "eprint_macro")]
127131
#[allow_internal_unstable(print_internals)]
128132
macro_rules! eprint {
129-
($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
133+
($($arg:tt)*) => {
134+
$crate::io::_eprint($crate::format_args!($($arg)*))
135+
};
130136
}
131137

132138
/// Prints to the standard error, with a newline.
@@ -155,10 +161,12 @@ macro_rules! eprint {
155161
#[cfg_attr(not(test), rustc_diagnostic_item = "eprintln_macro")]
156162
#[allow_internal_unstable(print_internals, format_args_nl)]
157163
macro_rules! eprintln {
158-
() => ($crate::eprint!("\n"));
159-
($($arg:tt)*) => ({
160-
$crate::io::_eprint($crate::format_args_nl!($($arg)*));
161-
})
164+
() => {
165+
$crate::eprint!("\n")
166+
};
167+
($($arg:tt)*) => {
168+
$crate::io::_eprint($crate::format_args_nl!($($arg)*))
169+
};
162170
}
163171

164172
/// Prints and returns the value of a given expression for quick and dirty

‎src/test/pretty/dollar-crate.pp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// pp-exact:dollar-crate.pp
1010

1111
fn main() {
12-
{ ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], &[])); };
12+
::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], &[]));
1313
}

‎src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.closure.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@
116116
116| 1|
117117
117| 1| let
118118
118| 1| _unused_closure
119-
119| | =
120-
120| | |
119+
119| 1| =
120+
120| 1| |
121121
121| | mut countdown
122122
122| | |
123123
123| 0| {
@@ -173,7 +173,7 @@
173173
169| | ;
174174
170| |
175175
171| 1| let short_used_not_covered_closure_line_break_no_block_embedded_branch =
176-
172| | | _unused_arg: u8 |
176+
172| 1| | _unused_arg: u8 |
177177
173| 0| println!(
178178
174| 0| "not called: {}",
179179
175| 0| if is_true { "check" } else { "me" }
@@ -191,7 +191,7 @@
191191
187| | ;
192192
188| |
193193
189| 1| let short_used_covered_closure_line_break_no_block_embedded_branch =
194-
190| 1| | _unused_arg: u8 |
194+
190| | | _unused_arg: u8 |
195195
191| 1| println!(
196196
192| 1| "not called: {}",
197197
193| 1| if is_true { "check" } else { "me" }

‎src/test/ui/macros/trace-macro.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ LL | println!("Hello, World!");
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: expanding `println! { "Hello, World!" }`
8-
= note: to `{ $crate :: io :: _print($crate :: format_args_nl! ("Hello, World!")) ; }`
8+
= note: to `$crate :: io :: _print($crate :: format_args_nl! ("Hello, World!"))`
99

‎src/test/ui/mir/mir_let_chains_drop_order.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// See `mir_drop_order.rs` for more information
66

77
#![feature(let_chains)]
8+
#![allow(irrefutable_let_patterns)]
89

910
use std::cell::RefCell;
1011
use std::panic;

‎src/test/ui/parser/issues/issue-62894.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ LL | fn main() {}
4545
|
4646
::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
4747
|
48-
LL | ($left:expr, $right:expr $(,)?) => ({
48+
LL | ($left:expr, $right:expr $(,)?) => {
4949
| ---------- while parsing argument for this `expr` macro fragment
5050

5151
error: aborting due to 4 previous errors

‎src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ LL | struct Foo(isize, isize);
1212
= note: the matched value is of type `Foo`
1313
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1414
|
15-
LL ~ Foo(2, b) => println!("{}", b)
15+
LL ~ Foo(2, b) => println!("{}", b),
1616
LL + Foo(_, _) => todo!()
1717
|
1818

‎src/test/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// run-pass
22

33
#![feature(let_chains)]
4+
#![allow(irrefutable_let_patterns)]
45

56
fn main() {
67
let first = Some(1);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#![feature(let_chains, let_else)]
2+
3+
fn main() {
4+
let opt = Some(1i32);
5+
6+
let Some(n) = opt else {
7+
return;
8+
};
9+
let Some(n) = opt && n == 1 else {
10+
//~^ ERROR a `&&` expression cannot be directly assigned in `let...else`
11+
//~| ERROR mismatched types
12+
//~| ERROR mismatched types
13+
return;
14+
};
15+
let Some(n) = opt && let another = n else {
16+
//~^ ERROR a `&&` expression cannot be directly assigned in `let...else`
17+
//~| ERROR `let` expressions are not supported here
18+
//~| ERROR mismatched types
19+
//~| ERROR mismatched types
20+
return;
21+
};
22+
23+
if let Some(n) = opt else {
24+
//~^ ERROR missing condition for `if` expression
25+
return;
26+
};
27+
if let Some(n) = opt && n == 1 else {
28+
//~^ ERROR missing condition for `if` expression
29+
return;
30+
};
31+
if let Some(n) = opt && let another = n else {
32+
//~^ ERROR missing condition for `if` expression
33+
return;
34+
};
35+
36+
{
37+
while let Some(n) = opt else {
38+
//~^ ERROR expected `{`, found keyword `else`
39+
return;
40+
};
41+
}
42+
{
43+
while let Some(n) = opt && n == 1 else {
44+
//~^ ERROR expected `{`, found keyword `else`
45+
return;
46+
};
47+
}
48+
{
49+
while let Some(n) = opt && let another = n else {
50+
//~^ ERROR expected `{`, found keyword `else`
51+
return;
52+
};
53+
}
54+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
error: a `&&` expression cannot be directly assigned in `let...else`
2+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
3+
|
4+
LL | let Some(n) = opt && n == 1 else {
5+
| ^^^^^^^^^^^^^
6+
|
7+
help: wrap the expression in parentheses
8+
|
9+
LL | let Some(n) = (opt && n == 1) else {
10+
| + +
11+
12+
error: a `&&` expression cannot be directly assigned in `let...else`
13+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
14+
|
15+
LL | let Some(n) = opt && let another = n else {
16+
| ^^^^^^^^^^^^^^^^^^^^^^
17+
|
18+
help: wrap the expression in parentheses
19+
|
20+
LL | let Some(n) = (opt && let another = n) else {
21+
| + +
22+
23+
error: missing condition for `if` expression
24+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:7
25+
|
26+
LL | if let Some(n) = opt else {
27+
| ^ expected if condition here
28+
29+
error: missing condition for `if` expression
30+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:7
31+
|
32+
LL | if let Some(n) = opt && n == 1 else {
33+
| ^ expected if condition here
34+
35+
error: missing condition for `if` expression
36+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:7
37+
|
38+
LL | if let Some(n) = opt && let another = n else {
39+
| ^ expected if condition here
40+
41+
error: expected `{`, found keyword `else`
42+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33
43+
|
44+
LL | while let Some(n) = opt else {
45+
| ----- ----------------- ^^^^ expected `{`
46+
| | |
47+
| | this `while` condition successfully parsed
48+
| while parsing the body of this `while` expression
49+
50+
error: expected `{`, found keyword `else`
51+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:43:43
52+
|
53+
LL | while let Some(n) = opt && n == 1 else {
54+
| ----- --------------------------- ^^^^ expected `{`
55+
| | |
56+
| | this `while` condition successfully parsed
57+
| while parsing the body of this `while` expression
58+
59+
error: expected `{`, found keyword `else`
60+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:49:52
61+
|
62+
LL | while let Some(n) = opt && let another = n else {
63+
| ----- ------------------------------------ ^^^^ expected `{`
64+
| | |
65+
| | this `while` condition successfully parsed
66+
| while parsing the body of this `while` expression
67+
68+
error: `let` expressions are not supported here
69+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26
70+
|
71+
LL | let Some(n) = opt && let another = n else {
72+
| ^^^^^^^^^^^^^^^
73+
|
74+
= note: only supported directly in conditions of `if` and `while` expressions
75+
= note: as well as when nested within `&&` and parentheses in those conditions
76+
77+
error[E0308]: mismatched types
78+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
79+
|
80+
LL | let Some(n) = opt && n == 1 else {
81+
| ^^^ expected `bool`, found enum `Option`
82+
|
83+
= note: expected type `bool`
84+
found enum `Option<i32>`
85+
86+
error[E0308]: mismatched types
87+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:9
88+
|
89+
LL | let Some(n) = opt && n == 1 else {
90+
| ^^^^^^^ ------------- this expression has type `bool`
91+
| |
92+
| expected `bool`, found enum `Option`
93+
|
94+
= note: expected type `bool`
95+
found enum `Option<_>`
96+
97+
error[E0308]: mismatched types
98+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
99+
|
100+
LL | let Some(n) = opt && let another = n else {
101+
| ^^^ expected `bool`, found enum `Option`
102+
|
103+
= note: expected type `bool`
104+
found enum `Option<i32>`
105+
106+
error[E0308]: mismatched types
107+
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:9
108+
|
109+
LL | let Some(n) = opt && let another = n else {
110+
| ^^^^^^^ ---------------------- this expression has type `bool`
111+
| |
112+
| expected `bool`, found enum `Option`
113+
|
114+
= note: expected type `bool`
115+
found enum `Option<_>`
116+
117+
error: aborting due to 13 previous errors
118+
119+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
error: leading irrefutable pattern in let chain
2+
--> $DIR/irrefutable-lets.rs:13:8
3+
|
4+
LL | if let first = &opt && let Some(ref second) = first && let None = second.start {}
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/irrefutable-lets.rs:6:30
9+
|
10+
LL | #![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: this pattern will always match
13+
= help: consider moving it outside of the construct
14+
15+
error: irrefutable `if let` patterns
16+
--> $DIR/irrefutable-lets.rs:19:8
17+
|
18+
LL | if let first = &opt && let (a, b) = (1, 2) {}
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
|
21+
= note: these patterns will always match, so the `if let` is useless
22+
= help: consider replacing the `if let` with a `let`
23+
24+
error: leading irrefutable pattern in let chain
25+
--> $DIR/irrefutable-lets.rs:22:8
26+
|
27+
LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
28+
| ^^^^^^^^^^^^^^^^
29+
|
30+
= note: this pattern will always match
31+
= help: consider moving it outside of the construct
32+
33+
error: trailing irrefutable pattern in let chain
34+
--> $DIR/irrefutable-lets.rs:22:87
35+
|
36+
LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
37+
| ^^^^^^^^^
38+
|
39+
= note: this pattern will always match
40+
= help: consider moving it into the body
41+
42+
error: trailing irrefutable patterns in let chain
43+
--> $DIR/irrefutable-lets.rs:26:37
44+
|
45+
LL | if let Some(ref first) = opt && let second = first && let _third = second {}
46+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
|
48+
= note: these patterns will always match
49+
= help: consider moving them into the body
50+
51+
error: leading irrefutable pattern in let chain
52+
--> $DIR/irrefutable-lets.rs:29:8
53+
|
54+
LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {}
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
|
57+
= note: this pattern will always match
58+
= help: consider moving it outside of the construct
59+
60+
error: leading irrefutable pattern in let chain
61+
--> $DIR/irrefutable-lets.rs:32:8
62+
|
63+
LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {}
64+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65+
|
66+
= note: this pattern will always match
67+
= help: consider moving it outside of the construct
68+
69+
error: leading irrefutable pattern in let chain
70+
--> $DIR/irrefutable-lets.rs:35:8
71+
|
72+
LL | if let first = &opt && let None = Some(1) {}
73+
| ^^^^^^^^^^^^^^^^
74+
|
75+
= note: this pattern will always match
76+
= help: consider moving it outside of the construct
77+
78+
error: irrefutable `let` patterns
79+
--> $DIR/irrefutable-lets.rs:44:28
80+
|
81+
LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
82+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
83+
|
84+
= note: these patterns will always match, so the `let` is useless
85+
= help: consider removing `let`
86+
87+
error: leading irrefutable pattern in let chain
88+
--> $DIR/irrefutable-lets.rs:50:28
89+
|
90+
LL | Some(ref first) if let Range { start: local_start, end: _ } = first
91+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92+
|
93+
= note: this pattern will always match
94+
= help: consider moving it outside of the construct
95+
96+
error: irrefutable `while let` patterns
97+
--> $DIR/irrefutable-lets.rs:59:11
98+
|
99+
LL | while let first = &opt && let (a, b) = (1, 2) {}
100+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
101+
|
102+
= note: these patterns will always match, so the loop will never exit
103+
= help: consider instead using a `loop { ... }` with a `let` inside it
104+
105+
error: trailing irrefutable patterns in let chain
106+
--> $DIR/irrefutable-lets.rs:62:40
107+
|
108+
LL | while let Some(ref first) = opt && let second = first && let _third = second {}
109+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
110+
|
111+
= note: these patterns will always match
112+
= help: consider moving them into the body
113+
114+
error: aborting due to 12 previous errors
115+

‎src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,67 @@
1-
// check-pass
1+
// revisions: allowed disallowed
2+
//[allowed] check-pass
23

34
#![feature(if_let_guard, let_chains)]
5+
#![cfg_attr(allowed, allow(irrefutable_let_patterns))]
6+
#![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
47

58
use std::ops::Range;
69

710
fn main() {
811
let opt = Some(None..Some(1));
912

10-
if let first = &opt && let Some(ref second) = first && let None = second.start {
11-
}
12-
if let Some(ref first) = opt && let second = first && let _third = second {
13-
}
13+
if let first = &opt && let Some(ref second) = first && let None = second.start {}
14+
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
15+
16+
// No lint as the irrefutable pattern is surrounded by other stuff
17+
if 4 * 2 == 0 && let first = &opt && let Some(ref second) = first && let None = second.start {}
18+
19+
if let first = &opt && let (a, b) = (1, 2) {}
20+
//[disallowed]~^ ERROR irrefutable `if let` patterns
21+
22+
if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {}
23+
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
24+
//[disallowed]~^^ ERROR trailing irrefutable pattern in let chain
25+
26+
if let Some(ref first) = opt && let second = first && let _third = second {}
27+
//[disallowed]~^ ERROR trailing irrefutable patterns in let chain
28+
29+
if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {}
30+
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
31+
32+
if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {}
33+
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
34+
35+
if let first = &opt && let None = Some(1) {}
36+
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
37+
1438
if let Some(ref first) = opt
1539
&& let Range { start: local_start, end: _ } = first
1640
&& let None = local_start {
1741
}
1842

1943
match opt {
20-
Some(ref first) if let second = first && let _third = second => {},
44+
Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
45+
//[disallowed]~^ ERROR irrefutable `let` patterns
2146
_ => {}
2247
}
48+
2349
match opt {
2450
Some(ref first) if let Range { start: local_start, end: _ } = first
51+
//[disallowed]~^ ERROR leading irrefutable pattern in let chain
2552
&& let None = local_start => {},
2653
_ => {}
2754
}
2855

29-
while let first = &opt && let Some(ref second) = first && let None = second.start {
30-
}
31-
while let Some(ref first) = opt && let second = first && let _third = second {
32-
}
56+
// No error, despite the prefix being irrefutable
57+
while let first = &opt && let Some(ref second) = first && let None = second.start {}
58+
59+
while let first = &opt && let (a, b) = (1, 2) {}
60+
//[disallowed]~^ ERROR irrefutable `while let` patterns
61+
62+
while let Some(ref first) = opt && let second = first && let _third = second {}
63+
//[disallowed]~^ ERROR trailing irrefutable patterns in let chain
64+
3365
while let Some(ref first) = opt
3466
&& let Range { start: local_start, end: _ } = first
3567
&& let None = local_start {

0 commit comments

Comments
 (0)
Please sign in to comment.