Auto merge of #96863 - SparrowLii:let, r=michaelwoerister
use `hir::Let` in `hir::Guard::IfLet` This PR fixes the FIXME about using `hir::Let` in `hir::Guard::IfLet`
This commit is contained in:
commit
07ae142d77
18 changed files with 55 additions and 57 deletions
|
@ -505,8 +505,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||||
let pat = self.lower_pat(&arm.pat);
|
let pat = self.lower_pat(&arm.pat);
|
||||||
let guard = arm.guard.as_ref().map(|cond| {
|
let guard = arm.guard.as_ref().map(|cond| {
|
||||||
if let ExprKind::Let(ref pat, ref scrutinee, _) = cond.kind {
|
if let ExprKind::Let(ref pat, ref scrutinee, span) = cond.kind {
|
||||||
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee))
|
hir::Guard::IfLet(self.arena.alloc(hir::Let {
|
||||||
|
hir_id: self.next_id(),
|
||||||
|
span: self.lower_span(span),
|
||||||
|
pat: self.lower_pat(pat),
|
||||||
|
ty: None,
|
||||||
|
init: self.lower_expr(scrutinee),
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
hir::Guard::If(self.lower_expr(cond))
|
hir::Guard::If(self.lower_expr(cond))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1320,8 +1320,7 @@ pub struct Let<'hir> {
|
||||||
#[derive(Debug, HashStable_Generic)]
|
#[derive(Debug, HashStable_Generic)]
|
||||||
pub enum Guard<'hir> {
|
pub enum Guard<'hir> {
|
||||||
If(&'hir Expr<'hir>),
|
If(&'hir Expr<'hir>),
|
||||||
// FIXME use hir::Let for this.
|
IfLet(&'hir Let<'hir>),
|
||||||
IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, HashStable_Generic)]
|
#[derive(Debug, HashStable_Generic)]
|
||||||
|
|
|
@ -1225,9 +1225,8 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
|
||||||
if let Some(ref g) = arm.guard {
|
if let Some(ref g) = arm.guard {
|
||||||
match g {
|
match g {
|
||||||
Guard::If(ref e) => visitor.visit_expr(e),
|
Guard::If(ref e) => visitor.visit_expr(e),
|
||||||
Guard::IfLet(ref pat, ref e) => {
|
Guard::IfLet(ref l) => {
|
||||||
visitor.visit_pat(pat);
|
visitor.visit_let_expr(l);
|
||||||
visitor.visit_expr(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1915,14 +1915,9 @@ impl<'a> State<'a> {
|
||||||
self.print_expr(&e);
|
self.print_expr(&e);
|
||||||
self.space();
|
self.space();
|
||||||
}
|
}
|
||||||
hir::Guard::IfLet(pat, e) => {
|
hir::Guard::IfLet(hir::Let { pat, ty, init, .. }) => {
|
||||||
self.word_nbsp("if");
|
self.word_nbsp("if");
|
||||||
self.word_nbsp("let");
|
self.print_let(pat, *ty, init);
|
||||||
self.print_pat(&pat);
|
|
||||||
self.space();
|
|
||||||
self.word_space("=");
|
|
||||||
self.print_expr(&e);
|
|
||||||
self.space();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -798,8 +798,8 @@ impl<'tcx> Cx<'tcx> {
|
||||||
pattern: self.pattern_from_hir(&arm.pat),
|
pattern: self.pattern_from_hir(&arm.pat),
|
||||||
guard: arm.guard.as_ref().map(|g| match g {
|
guard: arm.guard.as_ref().map(|g| match g {
|
||||||
hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
|
hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
|
||||||
hir::Guard::IfLet(ref pat, ref e) => {
|
hir::Guard::IfLet(ref l) => {
|
||||||
Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr(e))
|
Guard::IfLet(self.pattern_from_hir(l.pat), self.mirror_expr(l.init))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
body: self.mirror_expr(arm.body),
|
body: self.mirror_expr(arm.body),
|
||||||
|
|
|
@ -173,10 +173,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||||
for arm in hir_arms {
|
for arm in hir_arms {
|
||||||
// Check the arm for some things unrelated to exhaustiveness.
|
// Check the arm for some things unrelated to exhaustiveness.
|
||||||
self.check_patterns(&arm.pat, Refutable);
|
self.check_patterns(&arm.pat, Refutable);
|
||||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard {
|
||||||
self.check_patterns(pat, Refutable);
|
self.check_patterns(let_expr.pat, Refutable);
|
||||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false);
|
let tpat = self.lower_pattern(&mut cx, let_expr.pat, &mut false);
|
||||||
self.check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span());
|
self.check_let_reachability(&mut cx, let_expr.pat.hir_id, tpat, tpat.span());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1108,9 +1108,9 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> L
|
||||||
|
|
||||||
match parent_node {
|
match parent_node {
|
||||||
hir::Node::Arm(hir::Arm {
|
hir::Node::Arm(hir::Arm {
|
||||||
guard: Some(hir::Guard::IfLet(&hir::Pat { hir_id, .. }, _)),
|
guard: Some(hir::Guard::IfLet(&hir::Let { pat: hir::Pat { hir_id, .. }, .. })),
|
||||||
..
|
..
|
||||||
}) if Some(hir_id) == pat_id => {
|
}) if Some(*hir_id) == pat_id => {
|
||||||
return LetSource::IfLetGuard;
|
return LetSource::IfLetGuard;
|
||||||
}
|
}
|
||||||
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {
|
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {
|
||||||
|
|
|
@ -373,8 +373,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
||||||
|
|
||||||
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
|
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
|
||||||
self.add_from_pat(&arm.pat);
|
self.add_from_pat(&arm.pat);
|
||||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard {
|
||||||
self.add_from_pat(pat);
|
self.add_from_pat(let_expr.pat);
|
||||||
}
|
}
|
||||||
intravisit::walk_arm(self, arm);
|
intravisit::walk_arm(self, arm);
|
||||||
}
|
}
|
||||||
|
@ -914,9 +914,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
|
|
||||||
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
|
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
|
||||||
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
|
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
|
||||||
hir::Guard::IfLet(pat, e) => {
|
hir::Guard::IfLet(let_expr) => {
|
||||||
let let_bind = self.define_bindings_in_pat(pat, body_succ);
|
let let_bind = self.define_bindings_in_pat(let_expr.pat, body_succ);
|
||||||
self.propagate_through_expr(e, let_bind)
|
self.propagate_through_expr(let_expr.init, let_bind)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);
|
let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);
|
||||||
|
|
|
@ -82,13 +82,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
hir::Guard::If(e) => {
|
hir::Guard::If(e) => {
|
||||||
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
|
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
|
||||||
}
|
}
|
||||||
hir::Guard::IfLet(pat, e) => {
|
hir::Guard::IfLet(l) => {
|
||||||
let scrutinee_ty = self.demand_scrutinee_type(
|
self.check_expr_let(l);
|
||||||
e,
|
|
||||||
pat.contains_explicit_ref_binding(),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
self.check_pat_top(&pat, scrutinee_ty, None, true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> {
|
pub(super) fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> {
|
||||||
// for let statements, this is done in check_stmt
|
// for let statements, this is done in check_stmt
|
||||||
let init = let_expr.init;
|
let init = let_expr.init;
|
||||||
self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");
|
self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");
|
||||||
|
|
|
@ -298,9 +298,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
Guard::If(ref e) => {
|
Guard::If(ref e) => {
|
||||||
self.visit_expr(e);
|
self.visit_expr(e);
|
||||||
}
|
}
|
||||||
Guard::IfLet(ref pat, ref e) => {
|
Guard::IfLet(ref l) => {
|
||||||
self.visit_pat(pat);
|
self.visit_let_expr(l);
|
||||||
self.visit_expr(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -344,9 +344,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
|
||||||
// B -> C and E -> F are added implicitly due to the traversal order.
|
// B -> C and E -> F are added implicitly due to the traversal order.
|
||||||
match guard {
|
match guard {
|
||||||
Some(Guard::If(expr)) => self.visit_expr(expr),
|
Some(Guard::If(expr)) => self.visit_expr(expr),
|
||||||
Some(Guard::IfLet(pat, expr)) => {
|
Some(Guard::IfLet(let_expr)) => {
|
||||||
self.visit_pat(pat);
|
self.visit_let_expr(let_expr);
|
||||||
self.visit_expr(expr);
|
|
||||||
}
|
}
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -625,8 +625,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
if let Some(hir::Guard::If(e)) = arm.guard {
|
if let Some(hir::Guard::If(e)) = arm.guard {
|
||||||
self.consume_expr(e)
|
self.consume_expr(e)
|
||||||
} else if let Some(hir::Guard::IfLet(_, ref e)) = arm.guard {
|
} else if let Some(hir::Guard::IfLet(ref l)) = arm.guard {
|
||||||
self.consume_expr(e)
|
self.consume_expr(l.init)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.consume_expr(arm.body);
|
self.consume_expr(arm.body);
|
||||||
|
|
|
@ -2,7 +2,9 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/typeck.rs:9:22
|
--> $DIR/typeck.rs:9:22
|
||||||
|
|
|
|
||||||
LL | Ok(x) if let Err(_) = x => {},
|
LL | Ok(x) if let Err(_) = x => {},
|
||||||
| ^^^^^^ expected enum `Option`, found enum `Result`
|
| ^^^^^^ - this expression has type `Option<bool>`
|
||||||
|
| |
|
||||||
|
| expected enum `Option`, found enum `Result`
|
||||||
|
|
|
|
||||||
= note: expected enum `Option<bool>`
|
= note: expected enum `Option<bool>`
|
||||||
found enum `Result<_, _>`
|
found enum `Result<_, _>`
|
||||||
|
@ -11,7 +13,9 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/typeck.rs:11:22
|
--> $DIR/typeck.rs:11:22
|
||||||
|
|
|
|
||||||
LL | Ok(x) if let 0 = x => {},
|
LL | Ok(x) if let 0 = x => {},
|
||||||
| ^ expected enum `Option`, found integer
|
| ^ - this expression has type `Option<bool>`
|
||||||
|
| |
|
||||||
|
| expected enum `Option`, found integer
|
||||||
|
|
|
|
||||||
= note: expected enum `Option<bool>`
|
= note: expected enum `Option<bool>`
|
||||||
found type `{integer}`
|
found type `{integer}`
|
||||||
|
|
|
@ -5,7 +5,7 @@ use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_s
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::MultiSpan;
|
use rustc_errors::MultiSpan;
|
||||||
use rustc_hir::LangItem::OptionNone;
|
use rustc_hir::LangItem::OptionNone;
|
||||||
use rustc_hir::{Arm, Expr, Guard, HirId, Pat, PatKind};
|
use rustc_hir::{Arm, Expr, Guard, HirId, Let, Pat, PatKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -109,7 +109,7 @@ fn check_arm<'tcx>(
|
||||||
(Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b),
|
(Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b),
|
||||||
};
|
};
|
||||||
// the binding must not be used in the if guard
|
// the binding must not be used in the if guard
|
||||||
if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(_, e))| !is_local_used(cx, *e, binding_id));
|
if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(Let { init: e, .. }))| !is_local_used(cx, *e, binding_id));
|
||||||
// ...or anywhere in the inner expression
|
// ...or anywhere in the inner expression
|
||||||
if match inner {
|
if match inner {
|
||||||
IfLetOrMatch::IfLet(_, _, body, els) => {
|
IfLetOrMatch::IfLet(_, _, body, els) => {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_errors::Applicability;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
hir_id::HirIdSet,
|
hir_id::HirIdSet,
|
||||||
intravisit::{walk_expr, Visitor},
|
intravisit::{walk_expr, Visitor},
|
||||||
Block, Expr, ExprKind, Guard, HirId, Pat, Stmt, StmtKind, UnOp,
|
Block, Expr, ExprKind, Guard, HirId, Let, Pat, Stmt, StmtKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
@ -478,7 +478,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
|
||||||
let mut is_map_used = self.is_map_used;
|
let mut is_map_used = self.is_map_used;
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
self.visit_pat(arm.pat);
|
self.visit_pat(arm.pat);
|
||||||
if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard {
|
if let Some(Guard::If(guard) | Guard::IfLet(&Let { init: guard, .. })) = arm.guard {
|
||||||
self.visit_non_tail_expr(guard);
|
self.visit_non_tail_expr(guard);
|
||||||
}
|
}
|
||||||
is_map_used |= self.visit_cond_arm(arm.body);
|
is_map_used |= self.visit_cond_arm(arm.body);
|
||||||
|
|
|
@ -596,7 +596,7 @@ impl<'tcx> SideEffectVisit<'tcx> {
|
||||||
let mut vars = std::mem::take(&mut self.ret_vars);
|
let mut vars = std::mem::take(&mut self.ret_vars);
|
||||||
let _ = arm.guard.as_ref().map(|guard| {
|
let _ = arm.guard.as_ref().map(|guard| {
|
||||||
self.visit_expr(match guard {
|
self.visit_expr(match guard {
|
||||||
Guard::If(expr) | Guard::IfLet(_, expr) => expr,
|
Guard::If(expr) | Guard::IfLet(Let { init: expr, .. }) => expr,
|
||||||
});
|
});
|
||||||
vars.append(&mut self.ret_vars);
|
vars.append(&mut self.ret_vars);
|
||||||
});
|
});
|
||||||
|
|
|
@ -315,11 +315,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
out!("if let Some(Guard::If({expr})) = {arm}.guard;");
|
out!("if let Some(Guard::If({expr})) = {arm}.guard;");
|
||||||
self.expr(expr);
|
self.expr(expr);
|
||||||
},
|
},
|
||||||
Some(hir::Guard::IfLet(pat, expr)) => {
|
Some(hir::Guard::IfLet(let_expr)) => {
|
||||||
bind!(self, pat, expr);
|
bind!(self, let_expr);
|
||||||
out!("if let Some(Guard::IfLet({pat}, {expr}) = {arm}.guard;");
|
out!("if let Some(Guard::IfLet({let_expr}) = {arm}.guard;");
|
||||||
self.pat(pat);
|
self.pat(field!(let_expr.pat));
|
||||||
self.expr(expr);
|
self.expr(field!(let_expr.init));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
self.expr(field!(arm.body));
|
self.expr(field!(arm.body));
|
||||||
|
|
|
@ -301,7 +301,9 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
|
fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(Guard::If(l), Guard::If(r)) => self.eq_expr(l, r),
|
(Guard::If(l), Guard::If(r)) => self.eq_expr(l, r),
|
||||||
(Guard::IfLet(lp, le), Guard::IfLet(rp, re)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
|
(Guard::IfLet(l), Guard::IfLet(r)) => {
|
||||||
|
self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
|
||||||
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -894,7 +896,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn hash_guard(&mut self, g: &Guard<'_>) {
|
pub fn hash_guard(&mut self, g: &Guard<'_>) {
|
||||||
match g {
|
match g {
|
||||||
Guard::If(expr) | Guard::IfLet(_, expr) => {
|
Guard::If(expr) | Guard::IfLet(Let { init: expr, .. }) => {
|
||||||
self.hash_expr(expr);
|
self.hash_expr(expr);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue