Auto merge of #115995 - matthiaskrgr:rollup-jukbrvq, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - #115965 (Add more if let guard tests) - #115978 (Copy 1.72.1 release notes to master) - #115983 (fix confusing let chain indentation in rustc_resolve) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
62d9034a0d
13 changed files with 310 additions and 7 deletions
10
RELEASES.md
10
RELEASES.md
|
@ -1,3 +1,13 @@
|
||||||
|
Version 1.72.1 (2023-09-19)
|
||||||
|
===========================
|
||||||
|
|
||||||
|
- [Adjust codegen change to improve LLVM codegen](https://github.com/rust-lang/rust/pull/115236)
|
||||||
|
- [rustdoc: Fix self ty params in objects with lifetimes](https://github.com/rust-lang/rust/pull/115276)
|
||||||
|
- [Fix regression in compile times](https://github.com/rust-lang/rust/pull/114948)
|
||||||
|
- Resolve some ICE regressions in the compiler:
|
||||||
|
- [#115215](https://github.com/rust-lang/rust/pull/115215)
|
||||||
|
- [#115559](https://github.com/rust-lang/rust/pull/115559)
|
||||||
|
|
||||||
Version 1.72.0 (2023-08-24)
|
Version 1.72.0 (2023-08-24)
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
|
|
@ -991,9 +991,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
if !is_prelude
|
if !is_prelude
|
||||||
&& let Some(max_vis) = max_vis.get()
|
&& let Some(max_vis) = max_vis.get()
|
||||||
&& !max_vis.is_at_least(import.expect_vis(), self.tcx)
|
&& !max_vis.is_at_least(import.expect_vis(), self.tcx)
|
||||||
{
|
{
|
||||||
self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, fluent::resolve_glob_import_doesnt_reexport);
|
self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, fluent::resolve_glob_import_doesnt_reexport);
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
static A: [i32; 5] = [1, 2, 3, 4, 5];
|
static A: [i32; 5] = [1, 2, 3, 4, 5];
|
||||||
|
|
||||||
async fn fun() {
|
async fn fun() {
|
||||||
let u = A[async { 1 }.await];
|
let u = A[async { 1 }.await];
|
||||||
match A {
|
match A {
|
||||||
i if async { true }.await => (),
|
i if async { true }.await => (),
|
||||||
|
i if let Some(1) = async { Some(1) }.await => (),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +21,7 @@ fn main() {
|
||||||
async {
|
async {
|
||||||
match A {
|
match A {
|
||||||
i if async { true }.await => (),
|
i if async { true }.await => (),
|
||||||
|
i if let Some(2) = async { Some(2) }.await => (),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
// [drop_tracking] compile-flags: -Zdrop-tracking
|
// [drop_tracking] compile-flags: -Zdrop-tracking
|
||||||
// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
|
// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
|
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
|
||||||
|
|
||||||
fn is_send_sync<T: Send + Sync>(_: T) {}
|
fn is_send_sync<T: Send + Sync>(_: T) {}
|
||||||
|
@ -14,6 +16,7 @@ async fn fun() {
|
||||||
unsafe {
|
unsafe {
|
||||||
match A {
|
match A {
|
||||||
i if async { true }.await => (),
|
i if async { true }.await => (),
|
||||||
|
i if let Some(1) = async { Some(1) }.await => (),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +30,7 @@ fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
match A {
|
match A {
|
||||||
i if async { true }.await => (),
|
i if async { true }.await => (),
|
||||||
|
i if let Some(2) = async { Some(2) }.await => (),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// check-pass
|
// check-pass
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
struct StructA {}
|
struct StructA {}
|
||||||
|
@ -22,3 +24,10 @@ async fn ice() {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn if_let() {
|
||||||
|
match Some(StructB {}) {
|
||||||
|
Some(struct_b) if let true = get_struct_a_async().await.fn_taking_struct_b(&struct_b) => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
enum Foo {
|
enum Foo {
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
|
@ -13,6 +16,7 @@ fn main() {
|
||||||
match *foo {
|
match *foo {
|
||||||
| A => println!("A"),
|
| A => println!("A"),
|
||||||
| B | C if 1 < 2 => println!("BC!"),
|
| B | C if 1 < 2 => println!("BC!"),
|
||||||
|
| D if let 1 = 1 => println!("D!"),
|
||||||
| _ => {},
|
| _ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// needs-unwind
|
// needs-unwind
|
||||||
|
|
||||||
#![feature(generators, generator_trait)]
|
#![feature(generators, generator_trait)]
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
#![allow(unused_assignments)]
|
#![allow(unused_assignments)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
|
@ -332,6 +333,16 @@ fn move_ref_pattern(a: &Allocator) {
|
||||||
let (ref _a, ref mut _b, _c, mut _d) = tup;
|
let (ref _a, ref mut _b, _c, mut _d) = tup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn if_let_guard(a: &Allocator, c: bool, d: i32) {
|
||||||
|
let foo = if c { Some(a.alloc()) } else { None };
|
||||||
|
|
||||||
|
match d == 0 {
|
||||||
|
false if let Some(a) = foo => { let b = a; }
|
||||||
|
true if let true = { drop(foo.unwrap_or_else(|| a.alloc())); d == 1 } => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
|
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
|
||||||
// Panic in the drop of `p` or `q` can leak
|
// Panic in the drop of `p` or `q` can leak
|
||||||
let exceptions = vec![8, 9];
|
let exceptions = vec![8, 9];
|
||||||
|
@ -497,6 +508,13 @@ fn main() {
|
||||||
|
|
||||||
run_test(|a| move_ref_pattern(a));
|
run_test(|a| move_ref_pattern(a));
|
||||||
|
|
||||||
|
run_test(|a| if_let_guard(a, true, 0));
|
||||||
|
run_test(|a| if_let_guard(a, true, 1));
|
||||||
|
run_test(|a| if_let_guard(a, true, 2));
|
||||||
|
run_test(|a| if_let_guard(a, false, 0));
|
||||||
|
run_test(|a| if_let_guard(a, false, 1));
|
||||||
|
run_test(|a| if_let_guard(a, false, 2));
|
||||||
|
|
||||||
run_test(|a| {
|
run_test(|a| {
|
||||||
panic_after_return(a);
|
panic_after_return(a);
|
||||||
});
|
});
|
||||||
|
|
26
tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
Normal file
26
tests/ui/rfcs/rfc-2294-if-let-guard/const-expr.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Ensure if let guards can be used in constant expressions.
|
||||||
|
// build-pass
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
|
const fn match_if_let(x: Option<i32>, y: Option<i32>) -> i32 {
|
||||||
|
match x {
|
||||||
|
None if let Some(a @ 5) = y => a,
|
||||||
|
Some(z) if let (Some(_), 12) = (y, z) => 2,
|
||||||
|
_ => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ASSERTS: usize = {
|
||||||
|
assert!(match_if_let(None, Some(5)) == 5);
|
||||||
|
assert!(match_if_let(Some(12), Some(3)) == 2);
|
||||||
|
assert!(match_if_let(None, Some(4)) == 3);
|
||||||
|
assert!(match_if_let(Some(11), Some(3)) == 3);
|
||||||
|
assert!(match_if_let(Some(12), None) == 3);
|
||||||
|
assert!(match_if_let(None, None) == 3);
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: [(); ASSERTS];
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
#![feature(let_chains)]
|
||||||
|
#![allow(irrefutable_let_patterns)]
|
||||||
|
|
||||||
|
fn same_pattern(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, 2) if let y = x && c => (),
|
||||||
|
(1, 2) if let z = x => (), //~ ERROR use of moved value: `x`
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn same_pattern_ok(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, 2) if c && let y = x => (),
|
||||||
|
(1, 2) if let z = x => (),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn different_patterns(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, _) if let y = x && c => (),
|
||||||
|
(_, 2) if let z = x => (), //~ ERROR use of moved value: `x`
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn different_patterns_ok(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, _) if c && let y = x => (),
|
||||||
|
(_, 2) if let z = x => (),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn or_pattern(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, _) | (_, 2) if let y = x && c => (), //~ ERROR use of moved value: `x`
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn or_pattern_ok(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, _) | (_, 2) if c && let y = x => (),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_in_arm(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, 2) if let y = x && c => false,
|
||||||
|
_ => { *x == 1 }, //~ ERROR use of moved value: `x`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_in_arm_ok(c: bool) {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, 2) if c && let y = x => false,
|
||||||
|
_ => { *x == 1 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,67 @@
|
||||||
|
error[E0382]: use of moved value: `x`
|
||||||
|
--> $DIR/move-guard-if-let-chain.rs:12:27
|
||||||
|
|
|
||||||
|
LL | let x: Box<_> = Box::new(1);
|
||||||
|
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||||
|
...
|
||||||
|
LL | (1, 2) if let y = x && c => (),
|
||||||
|
| - value moved here
|
||||||
|
LL | (1, 2) if let z = x => (),
|
||||||
|
| ^ value used here after move
|
||||||
|
|
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | (1, 2) if let ref y = x && c => (),
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0382]: use of moved value: `x`
|
||||||
|
--> $DIR/move-guard-if-let-chain.rs:36:27
|
||||||
|
|
|
||||||
|
LL | let x: Box<_> = Box::new(1);
|
||||||
|
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||||
|
...
|
||||||
|
LL | (1, _) if let y = x && c => (),
|
||||||
|
| - value moved here
|
||||||
|
LL | (_, 2) if let z = x => (),
|
||||||
|
| ^ value used here after move
|
||||||
|
|
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | (1, _) if let ref y = x && c => (),
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0382]: use of moved value: `x`
|
||||||
|
--> $DIR/move-guard-if-let-chain.rs:59:36
|
||||||
|
|
|
||||||
|
LL | let x: Box<_> = Box::new(1);
|
||||||
|
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||||
|
...
|
||||||
|
LL | (1, _) | (_, 2) if let y = x && c => (),
|
||||||
|
| - ^ value used here after move
|
||||||
|
| |
|
||||||
|
| value moved here
|
||||||
|
|
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | (1, _) | (_, 2) if let ref y = x && c => (),
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error[E0382]: use of moved value: `x`
|
||||||
|
--> $DIR/move-guard-if-let-chain.rs:82:16
|
||||||
|
|
|
||||||
|
LL | let x: Box<_> = Box::new(1);
|
||||||
|
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
|
||||||
|
...
|
||||||
|
LL | (1, 2) if let y = x && c => false,
|
||||||
|
| - value moved here
|
||||||
|
LL | _ => { *x == 1 },
|
||||||
|
| ^^ value used here after move
|
||||||
|
|
|
||||||
|
help: borrow this binding in the pattern to avoid moving the value
|
||||||
|
|
|
||||||
|
LL | (1, 2) if let ref y = x && c => false,
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0382`.
|
41
tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
Normal file
41
tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Check that borrowck knows that moves in the pattern for if-let guards
|
||||||
|
// only happen when the pattern is matched.
|
||||||
|
|
||||||
|
// build-pass
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
#![allow(irrefutable_let_patterns)]
|
||||||
|
|
||||||
|
fn same_pattern() {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, 2) if let y = x => (),
|
||||||
|
(1, 2) if let z = x => (),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn or_pattern() {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, _) | (_, 2) if let y = x => (),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: Box<_> = Box::new(1);
|
||||||
|
|
||||||
|
let v = (1, 2);
|
||||||
|
|
||||||
|
match v {
|
||||||
|
(1, 2) if let y = x => false,
|
||||||
|
_ => { *x == 1 },
|
||||||
|
};
|
||||||
|
}
|
16
tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
Normal file
16
tests/ui/rfcs/rfc-2294-if-let-guard/type-inference.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
fn get<T>() -> Option<T> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match get() {
|
||||||
|
x if let Some(S) = x => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,25 +2,32 @@
|
||||||
|
|
||||||
#![allow(unused_must_use)]
|
#![allow(unused_must_use)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#![allow(path_statements)]
|
#![allow(path_statements)]
|
||||||
#![allow(unreachable_code)]
|
#![allow(unreachable_code)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
fn id(x: bool) -> bool { x }
|
fn id(x: bool) -> bool {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
fn call_id() {
|
fn call_id() {
|
||||||
let c = panic!();
|
let c = panic!();
|
||||||
id(c);
|
id(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_id_2() { id(true) && id(return); }
|
fn call_id_2() {
|
||||||
|
id(true) && id(return);
|
||||||
|
}
|
||||||
|
|
||||||
fn call_id_3() { id(return) && id(return); }
|
fn call_id_3() {
|
||||||
|
id(return) && id(return);
|
||||||
|
}
|
||||||
|
|
||||||
fn ret_guard() {
|
fn ret_guard() {
|
||||||
match 2 {
|
match 2 {
|
||||||
x if (return) => { x; }
|
x if (return) => { x; }
|
||||||
|
x if let true = return => { x; }
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue