mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 02:33:55 +00:00
Rollup merge of #98574 - dingxiangfei2009:let-else-thir, r=oli-obk
Lower let-else in MIR This MR will switch to lower let-else statements in MIR building instead. To lower let-else in MIR, we build a mini-switch two branches. One branch leads to the matching case, and the other leads to the `else` block. This arrangement will allow temporary lifetime analysis running as-is so that the temporaries are properly extended according to the same rule applied to regular `let` statements. cc https://github.com/rust-lang/rust/issues/87335 Fix #98672
This commit is contained in:
commit
9e1af3fd82
@ -11,7 +11,7 @@ use rustc_lint::LateContext;
|
|||||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
|
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
|
||||||
let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
|
let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
|
||||||
([stmt, stmts @ ..], expr) => {
|
([stmt, stmts @ ..], expr) => {
|
||||||
if let StmtKind::Local(&Local { init: Some(e), .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
|
if let StmtKind::Local(&Local { init: Some(e), els: None, .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
|
||||||
(e, !stmts.is_empty() || expr.is_some())
|
(e, !stmts.is_empty() || expr.is_some())
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -1041,7 +1041,8 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
|
||||||
self.infallible_destructuring_match_linted |= infallible_destructuring_match::check(cx, local);
|
self.infallible_destructuring_match_linted |=
|
||||||
|
local.els.is_none() && infallible_destructuring_match::check(cx, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
||||||
|
@ -92,6 +92,7 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id);
|
if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id);
|
||||||
if let Some(init) = local.init;
|
if let Some(init) = local.init;
|
||||||
|
if local.els.is_none();
|
||||||
if !local.pat.span.from_expansion();
|
if !local.pat.span.from_expansion();
|
||||||
if has_no_effect(cx, init);
|
if has_no_effect(cx, init);
|
||||||
if let PatKind::Binding(_, _, ident, _) = local.pat.kind;
|
if let PatKind::Binding(_, _, ident, _) = local.pat.kind;
|
||||||
|
@ -10,7 +10,6 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
|
|||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::hygiene::DesugaringKind;
|
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
@ -203,9 +202,7 @@ fn check_final_expr<'tcx>(
|
|||||||
check_block_return(cx, ifblock);
|
check_block_return(cx, ifblock);
|
||||||
}
|
}
|
||||||
if let Some(else_clause) = else_clause_opt {
|
if let Some(else_clause) = else_clause_opt {
|
||||||
if expr.span.desugaring_kind() != Some(DesugaringKind::LetElse) {
|
check_final_expr(cx, else_clause, None, RetReplacement::Empty);
|
||||||
check_final_expr(cx, else_clause, None, RetReplacement::Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// a match expr, check all arms
|
// a match expr, check all arms
|
||||||
|
@ -102,7 +102,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> {
|
|||||||
impl HirEqInterExpr<'_, '_, '_> {
|
impl HirEqInterExpr<'_, '_, '_> {
|
||||||
pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
|
pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
|
||||||
match (&left.kind, &right.kind) {
|
match (&left.kind, &right.kind) {
|
||||||
(&StmtKind::Local(l), &StmtKind::Local(r)) => {
|
(&StmtKind::Local(l, ), &StmtKind::Local(r, )) => {
|
||||||
// This additional check ensures that the type of the locals are equivalent even if the init
|
// This additional check ensures that the type of the locals are equivalent even if the init
|
||||||
// expression or type have some inferred parts.
|
// expression or type have some inferred parts.
|
||||||
if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results {
|
if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results {
|
||||||
@ -117,6 +117,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
// these only get added if the init and type is equal.
|
// these only get added if the init and type is equal.
|
||||||
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
|
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
|
||||||
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
|
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
|
||||||
|
&& both(&l.els, &r.els, |l, r| self.eq_block(l, r))
|
||||||
&& self.eq_pat(l.pat, r.pat)
|
&& self.eq_pat(l.pat, r.pat)
|
||||||
},
|
},
|
||||||
(&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r),
|
(&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r),
|
||||||
@ -921,11 +922,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
std::mem::discriminant(&b.kind).hash(&mut self.s);
|
std::mem::discriminant(&b.kind).hash(&mut self.s);
|
||||||
|
|
||||||
match &b.kind {
|
match &b.kind {
|
||||||
StmtKind::Local(local) => {
|
StmtKind::Local(local, ) => {
|
||||||
self.hash_pat(local.pat);
|
self.hash_pat(local.pat);
|
||||||
if let Some(init) = local.init {
|
if let Some(init) = local.init {
|
||||||
self.hash_expr(init);
|
self.hash_expr(init);
|
||||||
}
|
}
|
||||||
|
if let Some(els) = local.els {
|
||||||
|
self.hash_block(els);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
StmtKind::Item(..) => {},
|
StmtKind::Item(..) => {},
|
||||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
|
StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user