From 638d9c3d48812402902ada560dd173473e129674 Mon Sep 17 00:00:00 2001 From: Cormac Relf Date: Tue, 15 Feb 2022 16:31:49 +1100 Subject: [PATCH 1/4] let-else: test for issue 93951 / temporary lifetimes --- .../ui/let-else/let-else-temp-borrowck.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/ui/let-else/let-else-temp-borrowck.rs diff --git a/src/test/ui/let-else/let-else-temp-borrowck.rs b/src/test/ui/let-else/let-else-temp-borrowck.rs new file mode 100644 index 0000000000000..1100c2ba3fd6d --- /dev/null +++ b/src/test/ui/let-else/let-else-temp-borrowck.rs @@ -0,0 +1,26 @@ +// check-pass +// +// from issue #93951, where borrowck complained the temporary that `foo(&x)` was stored in was to +// be dropped sometime after `x` was. It then suggested adding a semicolon that was already there. + +#![feature(let_else)] +use std::fmt::Debug; + +fn foo<'a>(x: &'a str) -> Result { + Ok(x) +} + +fn let_else() { + let x = String::from("Hey"); + let Ok(s) = foo(&x) else { return }; +} + +fn if_let() { + let x = String::from("Hey"); + let s = if let Ok(s) = foo(&x) { s } else { return }; +} + +fn main() { + let_else(); + if_let(); +} From 14283b207c06914229202784d066d88792c71701 Mon Sep 17 00:00:00 2001 From: Cormac Relf Date: Tue, 15 Feb 2022 17:42:50 +1100 Subject: [PATCH 2/4] let-else: add a test for warnings on let-else with diverging tail --- src/test/ui/let-else/let-else-then-diverge.rs | 19 +++++++++++++++++++ .../ui/let-else/let-else-then-diverge.stderr | 14 ++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/ui/let-else/let-else-then-diverge.rs create mode 100644 src/test/ui/let-else/let-else-then-diverge.stderr diff --git a/src/test/ui/let-else/let-else-then-diverge.rs b/src/test/ui/let-else/let-else-then-diverge.rs new file mode 100644 index 0000000000000..49633d943beea --- /dev/null +++ b/src/test/ui/let-else/let-else-then-diverge.rs @@ -0,0 +1,19 @@ +// +// popped up in in #94012, where an alternative desugaring was +// causing unreachable code errors + +#![feature(let_else)] +#![deny(unused_variables)] +#![deny(unreachable_code)] + +fn let_else_diverge() -> bool { + let Some(_) = Some("test") else { + let x = 5; //~ ERROR unused variable: `x` + return false; + }; + return true; +} + +fn main() { + let_else_diverge(); +} diff --git a/src/test/ui/let-else/let-else-then-diverge.stderr b/src/test/ui/let-else/let-else-then-diverge.stderr new file mode 100644 index 0000000000000..ceb61029d3863 --- /dev/null +++ b/src/test/ui/let-else/let-else-then-diverge.stderr @@ -0,0 +1,14 @@ +error: unused variable: `x` + --> $DIR/let-else-then-diverge.rs:11:13 + | +LL | let x = 5; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/let-else-then-diverge.rs:6:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 07539b89daebbff20f2b321932a1a06c3df93e3c Mon Sep 17 00:00:00 2001 From: Cormac Relf Date: Wed, 16 Feb 2022 19:36:04 +1100 Subject: [PATCH 3/4] let-else: use DropTemps to fix borrowck complaints This prevents *any* unreachable_code warnings on DropTemps, including from its other uses. --- compiler/rustc_ast_lowering/src/block.rs | 3 ++- compiler/rustc_typeck/src/check/expr.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 082c5bb783347..f0835fc2fb4fb 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -159,6 +159,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)), }); + let drop_temps = self.expr_drop_temps(span, if_expr, AttrVec::new()); if !self.sess.features_untracked().let_else { feature_err( &self.sess.parse_sess, @@ -168,6 +169,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) .emit(); } - if_expr + drop_temps } } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 0347b6a4ab82f..5f2daf9e170aa 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -225,6 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ExprKind::If(..) | ExprKind::Let(..) | ExprKind::Loop(..) + | ExprKind::DropTemps(..) | ExprKind::Match(..) => {} // If `expr` is a result of desugaring the try block and is an ok-wrapped // diverging expression (e.g. it arose from desugaring of `try { return }`), From d549ede9c4721e465f1fead1bc1b024755db9ddf Mon Sep 17 00:00:00 2001 From: Cormac Relf Date: Thu, 17 Feb 2022 01:04:34 +1100 Subject: [PATCH 4/4] let-else: add test for linting unused variables in the first place + remove actual unused vars from some other tests to be less distracting --- src/test/ui/let-else/let-else-allow-unused.rs | 5 +++-- src/test/ui/let-else/let-else-allow-unused.stderr | 14 ++++++++++++++ src/test/ui/let-else/let-else-temp-borrowck.rs | 4 ++-- src/test/ui/let-else/let-else-then-diverge.rs | 5 +++-- src/test/ui/let-else/let-else-then-diverge.stderr | 4 ++-- 5 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/let-else/let-else-allow-unused.stderr diff --git a/src/test/ui/let-else/let-else-allow-unused.rs b/src/test/ui/let-else/let-else-allow-unused.rs index bcd8c987628b3..894d01d0796c3 100644 --- a/src/test/ui/let-else/let-else-allow-unused.rs +++ b/src/test/ui/let-else/let-else-allow-unused.rs @@ -1,4 +1,3 @@ -// check-pass // issue #89807 #![feature(let_else)] @@ -6,9 +5,11 @@ #[deny(unused_variables)] fn main() { - let value = Some(String::new()); + let value = Some(5); #[allow(unused)] let banana = 1; #[allow(unused)] let Some(chaenomeles) = value else { return }; // OK + let Some(unused) = value else { return }; + //~^ ERROR unused variable: `unused` } diff --git a/src/test/ui/let-else/let-else-allow-unused.stderr b/src/test/ui/let-else/let-else-allow-unused.stderr new file mode 100644 index 0000000000000..c40c8abd92c56 --- /dev/null +++ b/src/test/ui/let-else/let-else-allow-unused.stderr @@ -0,0 +1,14 @@ +error: unused variable: `unused` + --> $DIR/let-else-allow-unused.rs:13:14 + | +LL | let Some(unused) = value else { return }; + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/let-else-allow-unused.rs:5:8 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/let-else/let-else-temp-borrowck.rs b/src/test/ui/let-else/let-else-temp-borrowck.rs index 1100c2ba3fd6d..9905fae719b8e 100644 --- a/src/test/ui/let-else/let-else-temp-borrowck.rs +++ b/src/test/ui/let-else/let-else-temp-borrowck.rs @@ -12,12 +12,12 @@ fn foo<'a>(x: &'a str) -> Result { fn let_else() { let x = String::from("Hey"); - let Ok(s) = foo(&x) else { return }; + let Ok(_) = foo(&x) else { return }; } fn if_let() { let x = String::from("Hey"); - let s = if let Ok(s) = foo(&x) { s } else { return }; + let _ = if let Ok(s) = foo(&x) { s } else { return }; } fn main() { diff --git a/src/test/ui/let-else/let-else-then-diverge.rs b/src/test/ui/let-else/let-else-then-diverge.rs index 49633d943beea..0b55f6b0deab1 100644 --- a/src/test/ui/let-else/let-else-then-diverge.rs +++ b/src/test/ui/let-else/let-else-then-diverge.rs @@ -1,6 +1,7 @@ -// // popped up in in #94012, where an alternative desugaring was -// causing unreachable code errors +// causing unreachable code errors, and also we needed to check +// that the desugaring's generated lints weren't applying to +// the whole else block. #![feature(let_else)] #![deny(unused_variables)] diff --git a/src/test/ui/let-else/let-else-then-diverge.stderr b/src/test/ui/let-else/let-else-then-diverge.stderr index ceb61029d3863..2a888f93c6b14 100644 --- a/src/test/ui/let-else/let-else-then-diverge.stderr +++ b/src/test/ui/let-else/let-else-then-diverge.stderr @@ -1,11 +1,11 @@ error: unused variable: `x` - --> $DIR/let-else-then-diverge.rs:11:13 + --> $DIR/let-else-then-diverge.rs:12:13 | LL | let x = 5; | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here - --> $DIR/let-else-then-diverge.rs:6:9 + --> $DIR/let-else-then-diverge.rs:7:9 | LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^