Skip to content

Commit e888a15

Browse files
committed
Auto merge of rust-lang#134039 - matthiaskrgr:rollup-ix8kdg1, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#133424 (Parse guard patterns) - rust-lang#133733 ( compiletest: show the difference between the normalized output and the actual output for lines which didn't match) - rust-lang#133993 (Fix: typo in E0751 error explanation) - rust-lang#134013 (Adds new intrinsic declaration) - rust-lang#134020 (Remove unnecessary `int_type_width_signed` function) - rust-lang#134024 (Advent of `tests/ui` (misc cleanups and improvements) [2/N]) - rust-lang#134038 (deps: Update psm) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f33a8c6 + 5b133fe commit e888a15

File tree

52 files changed

+739
-301
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+739
-301
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -2815,9 +2815,9 @@ dependencies = [
28152815

28162816
[[package]]
28172817
name = "psm"
2818-
version = "0.1.23"
2818+
version = "0.1.24"
28192819
source = "registry+https://github.com/rust-lang/crates.io-index"
2820-
checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205"
2820+
checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
28212821
dependencies = [
28222822
"cc",
28232823
]

compiler/rustc_ast/src/ast.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,11 @@ impl Pat {
627627
| PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),
628628

629629
// Trivial wrappers over inner patterns.
630-
PatKind::Box(s) | PatKind::Deref(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => {
631-
s.walk(it)
632-
}
630+
PatKind::Box(s)
631+
| PatKind::Deref(s)
632+
| PatKind::Ref(s, _)
633+
| PatKind::Paren(s)
634+
| PatKind::Guard(s, _) => s.walk(it),
633635

634636
// These patterns do not contain subpatterns, skip.
635637
PatKind::Wild
@@ -839,6 +841,9 @@ pub enum PatKind {
839841
// A never pattern `!`.
840842
Never,
841843

844+
/// A guard pattern (e.g., `x if guard(x)`).
845+
Guard(P<Pat>, P<Expr>),
846+
842847
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
843848
Paren(P<Pat>),
844849

compiler/rustc_ast/src/mut_visit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1525,6 +1525,10 @@ pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
15251525
visit_opt(e2, |e| vis.visit_expr(e));
15261526
vis.visit_span(span);
15271527
}
1528+
PatKind::Guard(p, e) => {
1529+
vis.visit_pat(p);
1530+
vis.visit_expr(e);
1531+
}
15281532
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
15291533
visit_thin_vec(elems, |elem| vis.visit_pat(elem))
15301534
}

compiler/rustc_ast/src/visit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,10 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
682682
visit_opt!(visitor, visit_expr, lower_bound);
683683
visit_opt!(visitor, visit_expr, upper_bound);
684684
}
685+
PatKind::Guard(subpattern, guard_condition) => {
686+
try_visit!(visitor.visit_pat(subpattern));
687+
try_visit!(visitor.visit_expr(guard_condition));
688+
}
685689
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
686690
PatKind::Err(_guar) => {}
687691
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {

compiler/rustc_ast_lowering/src/pat.rs

+2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
114114
self.lower_range_end(end, e2.is_some()),
115115
);
116116
}
117+
// FIXME(guard_patterns): lower pattern guards to HIR
118+
PatKind::Guard(inner, _) => pattern = inner,
117119
PatKind::Slice(pats) => break self.lower_pat_slice(pats),
118120
PatKind::Rest => {
119121
// If we reach here the `..` pattern is not semantically allowed.

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
556556
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
557557
gate_all!(explicit_tail_calls, "`become` expression is experimental");
558558
gate_all!(generic_const_items, "generic const items are experimental");
559+
gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
559560
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
560561
gate_all!(postfix_match, "postfix match is experimental");
561562
gate_all!(mut_ref, "mutable by-reference bindings are experimental");

compiler/rustc_ast_pretty/src/pprust/state.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,14 @@ impl<'a> State<'a> {
17091709
self.print_expr(e, FixupContext::default());
17101710
}
17111711
}
1712+
PatKind::Guard(subpat, condition) => {
1713+
self.popen();
1714+
self.print_pat(subpat);
1715+
self.space();
1716+
self.word_space("if");
1717+
self.print_expr(condition, FixupContext::default());
1718+
self.pclose();
1719+
}
17121720
PatKind::Slice(elts) => {
17131721
self.word("[");
17141722
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));

compiler/rustc_codegen_llvm/src/intrinsic.rs

+75-91
Original file line numberDiff line numberDiff line change
@@ -352,84 +352,84 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
352352
| sym::saturating_add
353353
| sym::saturating_sub => {
354354
let ty = arg_tys[0];
355-
match int_type_width_signed(ty, self) {
356-
Some((width, signed)) => match name {
357-
sym::ctlz | sym::cttz => {
358-
let y = self.const_bool(false);
359-
let ret = self.call_intrinsic(&format!("llvm.{name}.i{width}"), &[
360-
args[0].immediate(),
361-
y,
362-
]);
363-
364-
self.intcast(ret, llret_ty, false)
365-
}
366-
sym::ctlz_nonzero => {
367-
let y = self.const_bool(true);
368-
let llvm_name = &format!("llvm.ctlz.i{width}");
369-
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
370-
self.intcast(ret, llret_ty, false)
371-
}
372-
sym::cttz_nonzero => {
373-
let y = self.const_bool(true);
374-
let llvm_name = &format!("llvm.cttz.i{width}");
375-
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
376-
self.intcast(ret, llret_ty, false)
377-
}
378-
sym::ctpop => {
379-
let ret = self.call_intrinsic(&format!("llvm.ctpop.i{width}"), &[args
380-
[0]
381-
.immediate()]);
382-
self.intcast(ret, llret_ty, false)
383-
}
384-
sym::bswap => {
385-
if width == 8 {
386-
args[0].immediate() // byte swap a u8/i8 is just a no-op
387-
} else {
388-
self.call_intrinsic(&format!("llvm.bswap.i{width}"), &[
389-
args[0].immediate()
390-
])
391-
}
392-
}
393-
sym::bitreverse => self
394-
.call_intrinsic(&format!("llvm.bitreverse.i{width}"), &[
355+
if !ty.is_integral() {
356+
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
357+
span,
358+
name,
359+
ty,
360+
});
361+
return Ok(());
362+
}
363+
let (size, signed) = ty.int_size_and_signed(self.tcx);
364+
let width = size.bits();
365+
match name {
366+
sym::ctlz | sym::cttz => {
367+
let y = self.const_bool(false);
368+
let ret = self.call_intrinsic(&format!("llvm.{name}.i{width}"), &[
369+
args[0].immediate(),
370+
y,
371+
]);
372+
373+
self.intcast(ret, llret_ty, false)
374+
}
375+
sym::ctlz_nonzero => {
376+
let y = self.const_bool(true);
377+
let llvm_name = &format!("llvm.ctlz.i{width}");
378+
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
379+
self.intcast(ret, llret_ty, false)
380+
}
381+
sym::cttz_nonzero => {
382+
let y = self.const_bool(true);
383+
let llvm_name = &format!("llvm.cttz.i{width}");
384+
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
385+
self.intcast(ret, llret_ty, false)
386+
}
387+
sym::ctpop => {
388+
let ret = self.call_intrinsic(&format!("llvm.ctpop.i{width}"), &[
389+
args[0].immediate()
390+
]);
391+
self.intcast(ret, llret_ty, false)
392+
}
393+
sym::bswap => {
394+
if width == 8 {
395+
args[0].immediate() // byte swap a u8/i8 is just a no-op
396+
} else {
397+
self.call_intrinsic(&format!("llvm.bswap.i{width}"), &[
395398
args[0].immediate()
396-
]),
397-
sym::rotate_left | sym::rotate_right => {
398-
let is_left = name == sym::rotate_left;
399-
let val = args[0].immediate();
400-
let raw_shift = args[1].immediate();
401-
// rotate = funnel shift with first two args the same
402-
let llvm_name =
403-
&format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);
404-
405-
// llvm expects shift to be the same type as the values, but rust
406-
// always uses `u32`.
407-
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
408-
409-
self.call_intrinsic(llvm_name, &[val, val, raw_shift])
399+
])
410400
}
411-
sym::saturating_add | sym::saturating_sub => {
412-
let is_add = name == sym::saturating_add;
413-
let lhs = args[0].immediate();
414-
let rhs = args[1].immediate();
415-
let llvm_name = &format!(
416-
"llvm.{}{}.sat.i{}",
417-
if signed { 's' } else { 'u' },
418-
if is_add { "add" } else { "sub" },
419-
width
420-
);
421-
self.call_intrinsic(llvm_name, &[lhs, rhs])
422-
}
423-
_ => bug!(),
424-
},
425-
None => {
426-
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
427-
span,
428-
name,
429-
ty,
430-
});
431-
return Ok(());
432401
}
402+
sym::bitreverse => self
403+
.call_intrinsic(&format!("llvm.bitreverse.i{width}"), &[
404+
args[0].immediate()
405+
]),
406+
sym::rotate_left | sym::rotate_right => {
407+
let is_left = name == sym::rotate_left;
408+
let val = args[0].immediate();
409+
let raw_shift = args[1].immediate();
410+
// rotate = funnel shift with first two args the same
411+
let llvm_name =
412+
&format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);
413+
414+
// llvm expects shift to be the same type as the values, but rust
415+
// always uses `u32`.
416+
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
417+
418+
self.call_intrinsic(llvm_name, &[val, val, raw_shift])
419+
}
420+
sym::saturating_add | sym::saturating_sub => {
421+
let is_add = name == sym::saturating_add;
422+
let lhs = args[0].immediate();
423+
let rhs = args[1].immediate();
424+
let llvm_name = &format!(
425+
"llvm.{}{}.sat.i{}",
426+
if signed { 's' } else { 'u' },
427+
if is_add { "add" } else { "sub" },
428+
width
429+
);
430+
self.call_intrinsic(llvm_name, &[lhs, rhs])
431+
}
432+
_ => bug!(),
433433
}
434434
}
435435

@@ -2531,19 +2531,3 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
25312531

25322532
span_bug!(span, "unknown SIMD intrinsic");
25332533
}
2534-
2535-
// Returns the width of an int Ty, and if it's signed or not
2536-
// Returns None if the type is not an integer
2537-
// FIXME: there’s multiple of this functions, investigate using some of the already existing
2538-
// stuffs.
2539-
fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> {
2540-
match ty.kind() {
2541-
ty::Int(t) => {
2542-
Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.pointer_width)), true))
2543-
}
2544-
ty::Uint(t) => {
2545-
Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.pointer_width)), false))
2546-
}
2547-
_ => None,
2548-
}
2549-
}

compiler/rustc_error_codes/src/error_codes/E0751.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ impl !MyTrait for i32 { } // error!
99
```
1010

1111
Negative implementations are a promise that the trait will never be implemented
12-
for the given types. Therefore, both cannot exists at the same time.
12+
for the given types. Therefore, both cannot exist at the same time.

compiler/rustc_expand/src/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ pub fn parse_ast_fragment<'a>(
990990
}
991991
}
992992
AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
993-
AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
993+
AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_guard(
994994
None,
995995
RecoverComma::No,
996996
RecoverColon::Yes,

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ declare_features! (
505505
(incomplete, generic_const_items, "1.73.0", Some(113521)),
506506
/// Allows registering static items globally, possibly across crates, to iterate over at runtime.
507507
(unstable, global_registration, "1.80.0", Some(125119)),
508+
/// Allows using guards in patterns.
509+
(incomplete, guard_patterns, "CURRENT_RUSTC_VERSION", Some(129967)),
508510
/// Allows using `..=X` as a patterns in slices.
509511
(unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
510512
/// Allows `if let` guard in match arms.

compiler/rustc_lint/src/unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ impl EarlyLintPass for UnusedParens {
12351235
self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
12361236
},
12371237
// Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
1238-
Ident(.., Some(p)) | Box(p) | Deref(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
1238+
Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
12391239
// Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
12401240
// Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
12411241
Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),

compiler/rustc_parse/src/parser/expr.rs

+26-32
Original file line numberDiff line numberDiff line change
@@ -2631,7 +2631,7 @@ impl<'a> Parser<'a> {
26312631
};
26322632
self.bump(); // Eat `let` token
26332633
let lo = self.prev_token.span;
2634-
let pat = self.parse_pat_allow_top_alt(
2634+
let pat = self.parse_pat_no_top_guard(
26352635
None,
26362636
RecoverComma::Yes,
26372637
RecoverColon::Yes,
@@ -2778,7 +2778,7 @@ impl<'a> Parser<'a> {
27782778
};
27792779
// Try to parse the pattern `for ($PAT) in $EXPR`.
27802780
let pat = match (
2781-
self.parse_pat_allow_top_alt(
2781+
self.parse_pat_allow_top_guard(
27822782
None,
27832783
RecoverComma::Yes,
27842784
RecoverColon::Yes,
@@ -3241,7 +3241,7 @@ impl<'a> Parser<'a> {
32413241
// then we should recover.
32423242
let mut snapshot = this.create_snapshot_for_diagnostic();
32433243
let pattern_follows = snapshot
3244-
.parse_pat_allow_top_alt(
3244+
.parse_pat_no_top_guard(
32453245
None,
32463246
RecoverComma::Yes,
32473247
RecoverColon::Yes,
@@ -3315,43 +3315,37 @@ impl<'a> Parser<'a> {
33153315

33163316
fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> {
33173317
if self.token == token::OpenDelim(Delimiter::Parenthesis) {
3318-
// Detect and recover from `($pat if $cond) => $arm`.
33193318
let left = self.token.span;
3320-
match self.parse_pat_allow_top_alt(
3319+
let pat = self.parse_pat_no_top_guard(
33213320
None,
33223321
RecoverComma::Yes,
33233322
RecoverColon::Yes,
33243323
CommaRecoveryMode::EitherTupleOrPipe,
3325-
) {
3326-
Ok(pat) => Ok((pat, self.parse_match_arm_guard()?)),
3327-
Err(err)
3328-
if let prev_sp = self.prev_token.span
3329-
&& let true = self.eat_keyword(kw::If) =>
3330-
{
3331-
// We know for certain we've found `($pat if` so far.
3332-
let mut cond = match self.parse_match_guard_condition() {
3333-
Ok(cond) => cond,
3334-
Err(cond_err) => {
3335-
cond_err.cancel();
3336-
return Err(err);
3337-
}
3338-
};
3339-
err.cancel();
3340-
CondChecker::new(self).visit_expr(&mut cond);
3341-
self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]);
3342-
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
3343-
let right = self.prev_token.span;
3344-
self.dcx().emit_err(errors::ParenthesesInMatchPat {
3345-
span: vec![left, right],
3346-
sugg: errors::ParenthesesInMatchPatSugg { left, right },
3347-
});
3348-
Ok((self.mk_pat(left.to(prev_sp), ast::PatKind::Wild), Some(cond)))
3349-
}
3350-
Err(err) => Err(err),
3324+
)?;
3325+
if let ast::PatKind::Paren(subpat) = &pat.kind
3326+
&& let ast::PatKind::Guard(..) = &subpat.kind
3327+
{
3328+
// Detect and recover from `($pat if $cond) => $arm`.
3329+
// FIXME(guard_patterns): convert this to a normal guard instead
3330+
let span = pat.span;
3331+
let ast::PatKind::Paren(subpat) = pat.into_inner().kind else { unreachable!() };
3332+
let ast::PatKind::Guard(_, mut cond) = subpat.into_inner().kind else {
3333+
unreachable!()
3334+
};
3335+
self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
3336+
CondChecker::new(self).visit_expr(&mut cond);
3337+
let right = self.prev_token.span;
3338+
self.dcx().emit_err(errors::ParenthesesInMatchPat {
3339+
span: vec![left, right],
3340+
sugg: errors::ParenthesesInMatchPatSugg { left, right },
3341+
});
3342+
Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond)))
3343+
} else {
3344+
Ok((pat, self.parse_match_arm_guard()?))
33513345
}
33523346
} else {
33533347
// Regular parser flow:
3354-
let pat = self.parse_pat_allow_top_alt(
3348+
let pat = self.parse_pat_no_top_guard(
33553349
None,
33563350
RecoverComma::Yes,
33573351
RecoverColon::Yes,

0 commit comments

Comments
 (0)