Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #134039

Merged
merged 30 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f8e50d8
add `guard_patterns` unstable feature, without unstable book chapter …
max-niederman Aug 22, 2024
35bbc45
refactor pat parser method names/doc-comments to agree with RFC 3637
max-niederman Aug 23, 2024
9b8bfed
add guard pattern AST node
max-niederman Aug 22, 2024
a3a29f5
cover guard patterns in rustfmt
max-niederman Oct 7, 2024
f86915a
cover guard patterns in clippy lints
max-niederman Oct 6, 2024
962c014
parse guard patterns
Nadrieril Nov 24, 2024
483f9e2
Fix rustfmt according to review
Nadrieril Nov 24, 2024
120d6b2
Fix: typo in E0751 error explanation
LuanOldCode Dec 7, 2024
8aacd1c
compiletest: show the difference between the normalized output and th…
jyn514 Dec 2, 2024
2459dbb
Address review comments
Nadrieril Dec 7, 2024
18d7b9a
Remove unnecessary `int_type_width_signed` function
scottmcm Dec 8, 2024
73b00ca
Document `assign-assign.rs`
jieyouxu Dec 8, 2024
5a79963
Move `assign-assign.rs` to `tests/ui/codegen/assign-expr-unit-type.rs`
jieyouxu Dec 8, 2024
62c3160
Adjust `assign-imm-local-twice.rs`
jieyouxu Dec 8, 2024
5e07f6e
Move `assign-imm-local-twice.rs` to `tests/ui/borrowck/`
jieyouxu Dec 8, 2024
1e3328d
Document `assoc-lang-items.rs`
jieyouxu Dec 8, 2024
6959582
Move `assoc-lang-items.rs` to `tests/ui/lang-items/`
jieyouxu Dec 8, 2024
b815a93
Move `assoc-oddities-3.rs` under `tests/ui/parser/assoc/`
jieyouxu Dec 8, 2024
3a33522
Adjust `assoc-oddities-3.rs`
jieyouxu Dec 8, 2024
1247f01
Move `atomic-from-mut-not-available.rs` to `tests/ui/stdlib-unit-tests/`
jieyouxu Dec 8, 2024
754dec3
Adjust `atomic-from-mut-not-available.rs`
jieyouxu Dec 8, 2024
292fd0f
Adds new intrinsic declaration
BLANKatGITHUB Dec 7, 2024
dd875ed
deps: Update psm
ognevny Dec 8, 2024
1868c8f
Rollup merge of #133424 - Nadrieril:guard-patterns-parsing, r=fee1-dead
matthiaskrgr Dec 8, 2024
c05e7bd
Rollup merge of #133733 - jyn514:compiletest-diffs, r=jieyouxu
matthiaskrgr Dec 8, 2024
11b0430
Rollup merge of #133993 - LuanOldCode:fix-e0571-typo, r=compiler-errors
matthiaskrgr Dec 8, 2024
fe5f5fd
Rollup merge of #134013 - BLANKatGITHUB:intrinsic, r=saethlin
matthiaskrgr Dec 8, 2024
d619c40
Rollup merge of #134020 - scottmcm:fix-a-fixme, r=jieyouxu
matthiaskrgr Dec 8, 2024
1aab767
Rollup merge of #134024 - jieyouxu:ui-cleanup-2, r=Nadrieril
matthiaskrgr Dec 8, 2024
5b133fe
Rollup merge of #134038 - ognevny:update-psm, r=ChrisDenton
matthiaskrgr Dec 8, 2024
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
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2815,9 +2815,9 @@ dependencies = [

[[package]]
name = "psm"
version = "0.1.23"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205"
checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
dependencies = [
"cc",
]
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,11 @@ impl Pat {
| PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),

// Trivial wrappers over inner patterns.
PatKind::Box(s) | PatKind::Deref(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => {
s.walk(it)
}
PatKind::Box(s)
| PatKind::Deref(s)
| PatKind::Ref(s, _)
| PatKind::Paren(s)
| PatKind::Guard(s, _) => s.walk(it),

// These patterns do not contain subpatterns, skip.
PatKind::Wild
Expand Down Expand Up @@ -839,6 +841,9 @@ pub enum PatKind {
// A never pattern `!`.
Never,

/// A guard pattern (e.g., `x if guard(x)`).
Guard(P<Pat>, P<Expr>),

/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
Paren(P<Pat>),

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,10 @@ pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
visit_opt(e2, |e| vis.visit_expr(e));
vis.visit_span(span);
}
PatKind::Guard(p, e) => {
vis.visit_pat(p);
vis.visit_expr(e);
}
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
visit_thin_vec(elems, |elem| vis.visit_pat(elem))
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,10 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
visit_opt!(visitor, visit_expr, lower_bound);
visit_opt!(visitor, visit_expr, upper_bound);
}
PatKind::Guard(subpattern, guard_condition) => {
try_visit!(visitor.visit_pat(subpattern));
try_visit!(visitor.visit_expr(guard_condition));
}
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
PatKind::Err(_guar) => {}
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_range_end(end, e2.is_some()),
);
}
// FIXME(guard_patterns): lower pattern guards to HIR
PatKind::Guard(inner, _) => pattern = inner,
PatKind::Slice(pats) => break self.lower_pat_slice(pats),
PatKind::Rest => {
// If we reach here the `..` pattern is not semantically allowed.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(generic_const_items, "generic const items are experimental");
gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
gate_all!(postfix_match, "postfix match is experimental");
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,14 @@ impl<'a> State<'a> {
self.print_expr(e, FixupContext::default());
}
}
PatKind::Guard(subpat, condition) => {
self.popen();
self.print_pat(subpat);
self.space();
self.word_space("if");
self.print_expr(condition, FixupContext::default());
self.pclose();
}
PatKind::Slice(elts) => {
self.word("[");
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
Expand Down
166 changes: 75 additions & 91 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,84 +352,84 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
| sym::saturating_add
| sym::saturating_sub => {
let ty = arg_tys[0];
match int_type_width_signed(ty, self) {
Some((width, signed)) => match name {
sym::ctlz | sym::cttz => {
let y = self.const_bool(false);
let ret = self.call_intrinsic(&format!("llvm.{name}.i{width}"), &[
args[0].immediate(),
y,
]);

self.intcast(ret, llret_ty, false)
}
sym::ctlz_nonzero => {
let y = self.const_bool(true);
let llvm_name = &format!("llvm.ctlz.i{width}");
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
self.intcast(ret, llret_ty, false)
}
sym::cttz_nonzero => {
let y = self.const_bool(true);
let llvm_name = &format!("llvm.cttz.i{width}");
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
self.intcast(ret, llret_ty, false)
}
sym::ctpop => {
let ret = self.call_intrinsic(&format!("llvm.ctpop.i{width}"), &[args
[0]
.immediate()]);
self.intcast(ret, llret_ty, false)
}
sym::bswap => {
if width == 8 {
args[0].immediate() // byte swap a u8/i8 is just a no-op
} else {
self.call_intrinsic(&format!("llvm.bswap.i{width}"), &[
args[0].immediate()
])
}
}
sym::bitreverse => self
.call_intrinsic(&format!("llvm.bitreverse.i{width}"), &[
if !ty.is_integral() {
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
span,
name,
ty,
});
return Ok(());
}
let (size, signed) = ty.int_size_and_signed(self.tcx);
let width = size.bits();
match name {
sym::ctlz | sym::cttz => {
let y = self.const_bool(false);
let ret = self.call_intrinsic(&format!("llvm.{name}.i{width}"), &[
args[0].immediate(),
y,
]);

self.intcast(ret, llret_ty, false)
}
sym::ctlz_nonzero => {
let y = self.const_bool(true);
let llvm_name = &format!("llvm.ctlz.i{width}");
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
self.intcast(ret, llret_ty, false)
}
sym::cttz_nonzero => {
let y = self.const_bool(true);
let llvm_name = &format!("llvm.cttz.i{width}");
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
self.intcast(ret, llret_ty, false)
}
sym::ctpop => {
let ret = self.call_intrinsic(&format!("llvm.ctpop.i{width}"), &[
args[0].immediate()
]);
self.intcast(ret, llret_ty, false)
}
sym::bswap => {
if width == 8 {
args[0].immediate() // byte swap a u8/i8 is just a no-op
} else {
self.call_intrinsic(&format!("llvm.bswap.i{width}"), &[
args[0].immediate()
]),
sym::rotate_left | sym::rotate_right => {
let is_left = name == sym::rotate_left;
let val = args[0].immediate();
let raw_shift = args[1].immediate();
// rotate = funnel shift with first two args the same
let llvm_name =
&format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);

// llvm expects shift to be the same type as the values, but rust
// always uses `u32`.
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);

self.call_intrinsic(llvm_name, &[val, val, raw_shift])
])
}
sym::saturating_add | sym::saturating_sub => {
let is_add = name == sym::saturating_add;
let lhs = args[0].immediate();
let rhs = args[1].immediate();
let llvm_name = &format!(
"llvm.{}{}.sat.i{}",
if signed { 's' } else { 'u' },
if is_add { "add" } else { "sub" },
width
);
self.call_intrinsic(llvm_name, &[lhs, rhs])
}
_ => bug!(),
},
None => {
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
span,
name,
ty,
});
return Ok(());
}
sym::bitreverse => self
.call_intrinsic(&format!("llvm.bitreverse.i{width}"), &[
args[0].immediate()
]),
sym::rotate_left | sym::rotate_right => {
let is_left = name == sym::rotate_left;
let val = args[0].immediate();
let raw_shift = args[1].immediate();
// rotate = funnel shift with first two args the same
let llvm_name =
&format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);

// llvm expects shift to be the same type as the values, but rust
// always uses `u32`.
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);

self.call_intrinsic(llvm_name, &[val, val, raw_shift])
}
sym::saturating_add | sym::saturating_sub => {
let is_add = name == sym::saturating_add;
let lhs = args[0].immediate();
let rhs = args[1].immediate();
let llvm_name = &format!(
"llvm.{}{}.sat.i{}",
if signed { 's' } else { 'u' },
if is_add { "add" } else { "sub" },
width
);
self.call_intrinsic(llvm_name, &[lhs, rhs])
}
_ => bug!(),
}
}

Expand Down Expand Up @@ -2531,19 +2531,3 @@ fn generic_simd_intrinsic<'ll, 'tcx>(

span_bug!(span, "unknown SIMD intrinsic");
}

// Returns the width of an int Ty, and if it's signed or not
// Returns None if the type is not an integer
// FIXME: there’s multiple of this functions, investigate using some of the already existing
// stuffs.
fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> {
match ty.kind() {
ty::Int(t) => {
Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.pointer_width)), true))
}
ty::Uint(t) => {
Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.pointer_width)), false))
}
_ => None,
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes/E0751.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ impl !MyTrait for i32 { } // error!
```

Negative implementations are a promise that the trait will never be implemented
for the given types. Therefore, both cannot exists at the same time.
for the given types. Therefore, both cannot exist at the same time.
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ pub fn parse_ast_fragment<'a>(
}
}
AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_alt(
AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_guard(
None,
RecoverComma::No,
RecoverColon::Yes,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,8 @@ declare_features! (
(incomplete, generic_const_items, "1.73.0", Some(113521)),
/// Allows registering static items globally, possibly across crates, to iterate over at runtime.
(unstable, global_registration, "1.80.0", Some(125119)),
/// Allows using guards in patterns.
(incomplete, guard_patterns, "CURRENT_RUSTC_VERSION", Some(129967)),
/// Allows using `..=X` as a patterns in slices.
(unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
/// Allows `if let` guard in match arms.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ impl EarlyLintPass for UnusedParens {
self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
},
// Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
Ident(.., Some(p)) | Box(p) | Deref(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
// Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
// Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
Expand Down
58 changes: 26 additions & 32 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2631,7 +2631,7 @@ impl<'a> Parser<'a> {
};
self.bump(); // Eat `let` token
let lo = self.prev_token.span;
let pat = self.parse_pat_allow_top_alt(
let pat = self.parse_pat_no_top_guard(
None,
RecoverComma::Yes,
RecoverColon::Yes,
Expand Down Expand Up @@ -2778,7 +2778,7 @@ impl<'a> Parser<'a> {
};
// Try to parse the pattern `for ($PAT) in $EXPR`.
let pat = match (
self.parse_pat_allow_top_alt(
self.parse_pat_allow_top_guard(
None,
RecoverComma::Yes,
RecoverColon::Yes,
Expand Down Expand Up @@ -3241,7 +3241,7 @@ impl<'a> Parser<'a> {
// then we should recover.
let mut snapshot = this.create_snapshot_for_diagnostic();
let pattern_follows = snapshot
.parse_pat_allow_top_alt(
.parse_pat_no_top_guard(
None,
RecoverComma::Yes,
RecoverColon::Yes,
Expand Down Expand Up @@ -3315,43 +3315,37 @@ impl<'a> Parser<'a> {

fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> {
if self.token == token::OpenDelim(Delimiter::Parenthesis) {
// Detect and recover from `($pat if $cond) => $arm`.
let left = self.token.span;
match self.parse_pat_allow_top_alt(
let pat = self.parse_pat_no_top_guard(
None,
RecoverComma::Yes,
RecoverColon::Yes,
CommaRecoveryMode::EitherTupleOrPipe,
) {
Ok(pat) => Ok((pat, self.parse_match_arm_guard()?)),
Err(err)
if let prev_sp = self.prev_token.span
&& let true = self.eat_keyword(kw::If) =>
{
// We know for certain we've found `($pat if` so far.
let mut cond = match self.parse_match_guard_condition() {
Ok(cond) => cond,
Err(cond_err) => {
cond_err.cancel();
return Err(err);
}
};
err.cancel();
CondChecker::new(self).visit_expr(&mut cond);
self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]);
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
let right = self.prev_token.span;
self.dcx().emit_err(errors::ParenthesesInMatchPat {
span: vec![left, right],
sugg: errors::ParenthesesInMatchPatSugg { left, right },
});
Ok((self.mk_pat(left.to(prev_sp), ast::PatKind::Wild), Some(cond)))
}
Err(err) => Err(err),
)?;
if let ast::PatKind::Paren(subpat) = &pat.kind
&& let ast::PatKind::Guard(..) = &subpat.kind
{
// Detect and recover from `($pat if $cond) => $arm`.
// FIXME(guard_patterns): convert this to a normal guard instead
let span = pat.span;
let ast::PatKind::Paren(subpat) = pat.into_inner().kind else { unreachable!() };
let ast::PatKind::Guard(_, mut cond) = subpat.into_inner().kind else {
unreachable!()
};
self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
CondChecker::new(self).visit_expr(&mut cond);
let right = self.prev_token.span;
self.dcx().emit_err(errors::ParenthesesInMatchPat {
span: vec![left, right],
sugg: errors::ParenthesesInMatchPatSugg { left, right },
});
Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond)))
} else {
Ok((pat, self.parse_match_arm_guard()?))
}
} else {
// Regular parser flow:
let pat = self.parse_pat_allow_top_alt(
let pat = self.parse_pat_no_top_guard(
None,
RecoverComma::Yes,
RecoverColon::Yes,
Expand Down
Loading
Loading