diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 29d4fb9ef2597..17dda26d0b459 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -213,7 +213,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.insert(expr.span, expr.hir_id, Node::PatExpr(expr)); self.with_parent(expr.hir_id, |this| { - intravisit::walk_pat_expr(this, expr); + intravisit::walk_pat_expr(this, expr.hir_id, expr.span, &expr.kind); }); } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index abd314ae74c39..8029203c8f17b 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -117,9 +117,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { break hir::PatKind::Ref(self.lower_pat(inner), *mutbl); } PatKind::Range(e1, e2, Spanned { node: end, .. }) => { + let mut lower_end = |e: &Expr| { + &*self.arena.alloc(hir::PatExpr { + hir_id: self.lower_node_id(e.id), + span: e.span, + kind: self.lower_expr_within_pat(e, true), + }) + }; break hir::PatKind::Range( - e1.as_deref().map(|e| self.lower_expr_within_pat(e, true)), - e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)), + e1.as_deref().map(|e| lower_end(e)), + e2.as_deref().map(|e| lower_end(e)), self.lower_range_end(end, e2.is_some()), ); } @@ -370,16 +377,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // } // m!(S); // ``` - fn lower_expr_within_pat( - &mut self, - expr: &Expr, - allow_paths: bool, - ) -> &'hir hir::PatExpr<'hir> { + fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> hir::PatExprKind<'hir> { let err = |guar| hir::PatExprKind::Lit { lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))), negated: false, }; - let kind = match &expr.kind { + match &expr.kind { ExprKind::Lit(lit) => { hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false } } @@ -413,11 +416,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }); err(guar) } - }; - self.arena.alloc(hir::PatExpr { - hir_id: self.lower_node_id(expr.id), - span: expr.span, - kind, - }) + } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 740c3ee8c076b..ead0e5e017627 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1521,6 +1521,7 @@ impl fmt::Debug for DotDotPos { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct PatExpr<'hir> { + #[stable_hasher(ignore)] pub hir_id: HirId, pub span: Span, pub kind: PatExprKind<'hir>, @@ -1584,7 +1585,7 @@ pub enum PatKind<'hir> { Ref(&'hir Pat<'hir>, Mutability), /// A literal, const block or path. - Expr(&'hir PatExpr<'hir>), + Expr(PatExprKind<'hir>), /// A guard pattern (e.g., `x if guard(x)`). Guard(&'hir Pat<'hir>, &'hir Expr<'hir>), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ef863aca09052..001278aafff26 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -343,7 +343,7 @@ pub trait Visitor<'v>: Sized { walk_pat_field(self, f) } fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result { - walk_pat_expr(self, expr) + walk_pat_expr(self, expr.hir_id, expr.span, &expr.kind) } fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { walk_anon_const(self, c) @@ -688,7 +688,9 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V: try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_pat, optional_subpattern); } - PatKind::Expr(ref expression) => try_visit!(visitor.visit_pat_expr(expression)), + PatKind::Expr(ref expression) => { + try_visit!(walk_pat_expr(visitor, pattern.hir_id, pattern.span, expression)) + } PatKind::Range(ref lower_bound, ref upper_bound, _) => { visit_opt!(visitor, visit_pat_expr, lower_bound); visit_opt!(visitor, visit_pat_expr, upper_bound); @@ -713,12 +715,17 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' visitor.visit_pat(field.pat) } -pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result { - try_visit!(visitor.visit_id(expr.hir_id)); - match &expr.kind { +pub fn walk_pat_expr<'v, V: Visitor<'v>>( + visitor: &mut V, + hir_id: HirId, + span: Span, + kind: &'v PatExprKind<'v>, +) -> V::Result { + try_visit!(visitor.visit_id(hir_id)); + match kind { PatExprKind::Lit { .. } => V::Result::output(), PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c), - PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span), + PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, hir_id, span), } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 3ff6acd79fcb6..f581625b84e89 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -199,7 +199,7 @@ impl<'a> State<'a> { Node::OpaqueTy(o) => self.print_opaque_ty(o), Node::Pat(a) => self.print_pat(a), Node::PatField(a) => self.print_patfield(a), - Node::PatExpr(a) => self.print_pat_expr(a), + Node::PatExpr(a) => self.print_pat_expr(&a.kind), Node::Arm(a) => self.print_arm(a), Node::Infer(_) => self.word("_"), Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident), @@ -1850,8 +1850,8 @@ impl<'a> State<'a> { } } - fn print_pat_expr(&mut self, expr: &hir::PatExpr<'_>) { - match &expr.kind { + fn print_pat_expr(&mut self, kind: &hir::PatExprKind<'_>) { + match kind { hir::PatExprKind::Lit { lit, negated } => { if *negated { self.word("-"); @@ -1980,17 +1980,17 @@ impl<'a> State<'a> { self.pclose(); } } - PatKind::Expr(e) => self.print_pat_expr(e), + PatKind::Expr(ref e) => self.print_pat_expr(e), PatKind::Range(begin, end, end_kind) => { if let Some(expr) = begin { - self.print_pat_expr(expr); + self.print_pat_expr(&expr.kind); } match end_kind { RangeEnd::Included => self.word("..."), RangeEnd::Excluded => self.word(".."), } if let Some(expr) = end { - self.print_pat_expr(expr); + self.print_pat_expr(&expr.kind); } } PatKind::Slice(before, slice, after) => { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 36094657eafd1..123a4813e2634 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -256,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => None, }; - let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); + let (adjust_mode, opt_expr_ty) = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); let (expected, binding_mode, max_ref_mutbl) = self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl); let pat_info = PatInfo { @@ -271,7 +271,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, - PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti), + PatKind::Expr(ref lt) => { + self.check_pat_lit(pat.hir_id, pat.span, lt, expected, ti, opt_expr_ty.unwrap()) + } PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), PatKind::Binding(ba, var_id, ident, sub) => { self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info) @@ -376,13 +378,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// How should the binding mode and expected type be adjusted? /// /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. - fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> AdjustMode { + /// + /// Returns the unadjusted type for expr patterns. + fn calc_adjust_mode( + &self, + pat: &'tcx Pat<'tcx>, + opt_path_res: Option, + ) -> (AdjustMode, Option>) { // When we perform destructuring assignment, we disable default match bindings, which are // unintuitive in this context. if !pat.default_binding_modes { - return AdjustMode::Reset; + return (AdjustMode::Reset, None); } - match &pat.kind { + let adjust = match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. PatKind::Struct(..) @@ -399,9 +407,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`. // // Call `resolve_vars_if_possible` here for inline const blocks. - PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() { - ty::Ref(..) => AdjustMode::Pass, - _ => AdjustMode::Peel, + PatKind::Expr(lt) => { + let ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt, pat.hir_id, pat.span)); + let adjust = match ty.kind() { + ty::Ref(..) => AdjustMode::Pass, + _ => AdjustMode::Peel, + }; + return (adjust, Some(ty)) }, PatKind::Path(_) => match opt_path_res.unwrap() { // These constants can be of a reference type, e.g. `const X: &u8 = &0;`. @@ -431,7 +443,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Or(_) // Like or-patterns, guard patterns just propogate to their subpatterns. | PatKind::Guard(..) => AdjustMode::Pass, - } + }; + (adjust, None) } /// Peel off as many immediately nested `& mut?` from the expected type as possible @@ -494,8 +507,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (expected, def_br, max_ref_mutbl) } - fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { - let ty = match <.kind { + fn check_pat_expr_unadjusted( + &self, + kind: &'tcx hir::PatExprKind<'tcx>, + hir_id: HirId, + span: Span, + ) -> Ty<'tcx> { + match kind { rustc_hir::PatExprKind::Lit { lit, .. } => { self.check_expr_lit(lit, Expectation::NoExpectation) } @@ -504,42 +522,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } rustc_hir::PatExprKind::Path(qpath) => { let (res, opt_ty, segments) = - self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span); - self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0 + self.resolve_ty_and_res_fully_qualified_call(qpath, hir_id, span); + self.instantiate_value_path(segments, opt_ty, res, span, span, hir_id).0 } - }; - self.write_ty(lt.hir_id, ty); - ty + } } fn check_pat_lit( &self, + hir_id: HirId, span: Span, - lt: &hir::PatExpr<'tcx>, + lt: &hir::PatExprKind<'tcx>, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, + mut pat_ty: Ty<'tcx>, ) -> Ty<'tcx> { - // We've already computed the type above (when checking for a non-ref pat), - // so avoid computing it again. - let ty = self.node_ty(lt.hir_id); - // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically-sized byte arrays. - let mut pat_ty = ty; if let hir::PatExprKind::Lit { lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, .. - } = lt.kind + } = lt { let expected = self.structurally_resolve_type(span, expected); if let ty::Ref(_, inner_ty, _) = *expected.kind() && self.try_structurally_resolve_type(span, inner_ty).is_slice() { let tcx = self.tcx; - trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); - self.typeck_results - .borrow_mut() - .treat_byte_string_as_slice - .insert(lt.hir_id.local_id); + trace!(?hir_id.local_id, "polymorphic byte string lit"); + self.typeck_results.borrow_mut().lit_pat_type_adjusted.insert(hir_id.local_id); pat_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8)); } @@ -548,10 +558,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.features().string_deref_patterns() && let hir::PatExprKind::Lit { lit: Spanned { node: ast::LitKind::Str(..), .. }, .. - } = lt.kind + } = lt { let tcx = self.tcx; let expected = self.resolve_vars_if_possible(expected); + self.typeck_results.borrow_mut().lit_pat_type_adjusted.insert(hir_id.local_id); pat_ty = match expected.kind() { ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected, ty::Str => Ty::new_static_str(tcx), @@ -597,7 +608,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr { None => None, Some(expr) => { - let ty = self.check_pat_expr_unadjusted(expr); + let ty = self.check_pat_expr_unadjusted(&expr.kind, expr.hir_id, expr.span); + + self.write_ty(expr.hir_id, ty); // Check that the end-point is possibly of numeric or char type. // The early check here is not for correctness, but rather better // diagnostics (e.g. when `&str` is being matched, `expected` will diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 683cacdff7d78..a1cf9859a81ac 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -79,8 +79,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); wbcx.typeck_results.used_trait_imports = used_trait_imports; - wbcx.typeck_results.treat_byte_string_as_slice = - mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice); + wbcx.typeck_results.lit_pat_type_adjusted = + mem::take(&mut self.typeck_results.borrow_mut().lit_pat_type_adjusted); debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results); @@ -328,6 +328,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { self.visit_field_id(field.hir_id); } } + hir::PatKind::Expr(hir::PatExprKind::ConstBlock(ref c)) => { + self.visit_const_block(p.span, c); + } _ => {} }; @@ -344,7 +347,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { if let hir::PatExprKind::ConstBlock(c) = &expr.kind { self.visit_const_block(expr.span, c); } - intravisit::walk_pat_expr(self, expr); + intravisit::walk_pat_expr(self, expr.hir_id, expr.span, &expr.kind); } fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index f94f52e4f6180..b764a95709b70 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -199,11 +199,13 @@ pub struct TypeckResults<'tcx> { /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>, - /// We sometimes treat byte string literals (which are of type `&[u8; N]`) - /// as `&[u8]`, depending on the pattern in which they are used. + /// We sometimes treat + /// * byte string literals (which are of type `&[u8; N]`) + /// as `&[u8]`, depending on the pattern in which they are used. + /// * string literals (which are of type `&str`) as `String` /// This hashset records all instances where we behave /// like this to allow `const_to_pat` to reliably handle this situation. - pub treat_byte_string_as_slice: ItemLocalSet, + pub lit_pat_type_adjusted: ItemLocalSet, /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` /// on closure size. @@ -239,7 +241,7 @@ impl<'tcx> TypeckResults<'tcx> { closure_fake_reads: Default::default(), rvalue_scopes: Default::default(), coroutine_stalled_predicates: Default::default(), - treat_byte_string_as_slice: Default::default(), + lit_pat_type_adjusted: Default::default(), closure_size_eval: Default::default(), offset_of_data: Default::default(), } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 49db522cf0eed..7e36ba245a148 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -33,7 +33,7 @@ pub(crate) fn lit_to_const<'tcx>( }; let valtree = match (lit, ty.kind()) { - (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { + (ast::LitKind::Str(s, _), _) => { let str_bytes = s.as_str().as_bytes(); ty::ValTree::from_raw_bytes(tcx, str_bytes) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 3853b95f78b4c..68763ecaf0747 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -4,7 +4,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; -use rustc_hir as hir; +use rustc_hir::{self as hir, LangItem}; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; @@ -58,7 +58,7 @@ struct ConstToPat<'tcx> { span: Span, id: hir::HirId, - treat_byte_string_as_slice: bool, + lit_pat_type_adjusted: bool, c: ty::Const<'tcx>, } @@ -71,9 +71,9 @@ impl<'tcx> ConstToPat<'tcx> { typing_env: pat_ctxt.typing_env, span, id, - treat_byte_string_as_slice: pat_ctxt + lit_pat_type_adjusted: pat_ctxt .typeck_results - .treat_byte_string_as_slice + .lit_pat_type_adjusted .contains(&id.local_id), c, } @@ -108,7 +108,7 @@ impl<'tcx> ConstToPat<'tcx> { uv: ty::UnevaluatedConst<'tcx>, ty: Ty<'tcx>, ) -> Box> { - trace!(self.treat_byte_string_as_slice); + trace!(self.lit_pat_type_adjusted); // It's not *technically* correct to be revealing opaque types here as borrowcheck has // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even @@ -219,6 +219,13 @@ impl<'tcx> ConstToPat<'tcx> { let span = self.span; let tcx = self.tcx; let kind = match ty.kind() { + ty::Adt(adt_def, _) + if self.lit_pat_type_adjusted + && tcx.is_lang_item(adt_def.did(), LangItem::String) => + { + let ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, tcx.types.str_); + PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) } + } ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { // Extremely important check for all ADTs! Make sure they opted-in to be used in // patterns. @@ -313,7 +320,7 @@ impl<'tcx> ConstToPat<'tcx> { // has no negative effects on pattern matching, even if we're actually matching on // arrays. let pointee_ty = match *pointee_ty.kind() { - ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => { + ty::Array(elem_ty, _) if self.lit_pat_type_adjusted => { Ty::new_slice(tcx, elem_ty) } _ => *pointee_ty, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 44b038bb5faf1..21c3639f81292 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -10,7 +10,7 @@ use rustc_errors::MultiSpan; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{self as hir, ByRef, Mutability, RangeEnd}; +use rustc_hir::{self as hir, ByRef, HirId, Mutability, RangeEnd}; use rustc_index::Idx; use rustc_lint as lint; use rustc_middle::mir::interpret::LitToConstInput; @@ -162,18 +162,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match expr { None => Ok((None, None, None)), Some(expr) => { - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; + let (kind, ascr, inline_const) = + match self.lower_lit(expr.hir_id, expr.span, &expr.kind) { + PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { + (subpattern.kind, None, def_id.as_local()) + } + PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { + (subpattern.kind, None, None) + } + PatKind::AscribeUserType { + ascription, + subpattern: box Pat { kind, .. }, + } => (kind, Some(ascription), None), + kind => (kind, None, None), + }; let value = match kind { PatKind::Constant { value } => value, PatKind::ExpandedConstant { subpattern, .. } @@ -324,7 +326,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Never => PatKind::Never, - hir::PatKind::Expr(value) => self.lower_lit(value), + hir::PatKind::Expr(ref value) => self.lower_lit(pat.hir_id, pat.span, value), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); @@ -656,21 +658,26 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// The special case for negation exists to allow things like `-128_i8` /// which would overflow if we tried to evaluate `128_i8` and then negate /// afterwards. - fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> { - let (lit, neg) = match &expr.kind { + fn lower_lit( + &mut self, + hir_id: HirId, + span: Span, + kind: &'tcx hir::PatExprKind<'tcx>, + ) -> PatKind<'tcx> { + let (lit, neg) = match &kind { hir::PatExprKind::Path(qpath) => { - return self.lower_path(qpath, expr.hir_id, expr.span).kind; + return self.lower_path(qpath, hir_id, span).kind; } hir::PatExprKind::ConstBlock(anon_const) => { - return self.lower_inline_const(anon_const, expr.hir_id, expr.span); + return self.lower_inline_const(anon_const, hir_id, span); } hir::PatExprKind::Lit { lit, negated } => (lit, *negated), }; - let ct_ty = self.typeck_results.node_type(expr.hir_id); + let ct_ty = self.typeck_results.node_type(hir_id); let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; - let constant = self.tcx.at(expr.span).lit_to_const(lit_input); - self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind + let constant = self.tcx.at(span).lit_to_const(lit_input); + self.const_to_pat(constant, ct_ty, hir_id, lit.span).kind } } diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index c04a73c890f0e..3bc63c0b899c7 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr, walk_pat, walk_stmt}; use rustc_hir::{ - Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Pat, PatExpr, PatExprKind, PatKind, Stmt, StmtKind, + Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Pat, PatExprKind, PatKind, Stmt, StmtKind, StructTailExpr, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -224,13 +224,9 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> { fn visit_pat(&mut self, pat: &'tcx Pat<'_>) { match pat.kind { - PatKind::Expr(&PatExpr { - hir_id, - kind: PatExprKind::Lit { lit, .. }, - .. - }) => { - let ty = self.cx.typeck_results().node_type(hir_id); - self.check_lit(lit, ty, hir_id); + PatKind::Expr(PatExprKind::Lit { lit, .. }) => { + let ty = self.cx.typeck_results().node_type(pat.hir_id); + self.check_lit(lit, ty, pat.hir_id); return; }, _ => {}, diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 5418acc105ebc..1a6a765e880b9 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -164,11 +164,8 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if let ExprKind::Let(lt) = expr.kind && match lt.pat.kind { PatKind::Slice([], None, []) => true, - PatKind::Expr(lit) => match lit.kind { - PatExprKind::Lit { lit, .. } => match lit.node { - LitKind::Str(lit, _) => lit.as_str().is_empty(), - _ => false, - }, + PatKind::Expr(PatExprKind::Lit { lit, .. }) => match lit.node { + LitKind::Str(lit, _) => lit.as_str().is_empty(), _ => false, }, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index 2e5a92915d9ca..88f28b5a0061c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{PatExpr, PatExprKind, PatKind, RangeEnd}; +use rustc_hir::{PatExprKind, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; @@ -38,8 +38,8 @@ declare_clippy_lint! { } declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]); -fn expr_as_i128(expr: &PatExpr<'_>) -> Option { - if let PatExprKind::Lit { lit, negated } = expr.kind +fn expr_as_i128(expr: &PatExprKind<'_>) -> Option { + if let PatExprKind::Lit { lit, negated } = *expr && let LitKind::Int(num, _) = lit.node { // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now. @@ -57,10 +57,10 @@ struct Num { } impl Num { - fn new(expr: &PatExpr<'_>) -> Option { + fn new(expr: &PatExprKind<'_>, span: Span) -> Option { Some(Self { val: expr_as_i128(expr)?, - span: expr.span, + span, }) } @@ -89,8 +89,8 @@ impl LateLintPass<'_> for ManualRangePatterns { let mut ranges_found = Vec::new(); for pat in pats { - if let PatKind::Expr(lit) = pat.kind - && let Some(num) = Num::new(lit) + if let PatKind::Expr(lit) = &pat.kind + && let Some(num) = Num::new(lit, pat.span) { numbers_found.insert(num.val); @@ -100,8 +100,8 @@ impl LateLintPass<'_> for ManualRangePatterns { range_kind = RangeEnd::Included; } } else if let PatKind::Range(Some(left), Some(right), end) = pat.kind - && let Some(left) = Num::new(left) - && let Some(mut right) = Num::new(right) + && let Some(left) = Num::new(&left.kind, left.span) + && let Some(mut right) = Num::new(&right.kind, right.span) { if let RangeEnd::Excluded = end { right.val -= 1; diff --git a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs index 7e43d222a6623..5a1cb22badb23 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs @@ -21,15 +21,11 @@ pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>] move |diag| { if arms.len() == 2 { // no guards - let exprs = if let PatKind::Expr(arm_bool) = arms[0].pat.kind { - if let PatExprKind::Lit { lit, .. } = arm_bool.kind { - match lit.node { - LitKind::Bool(true) => Some((arms[0].body, arms[1].body)), - LitKind::Bool(false) => Some((arms[1].body, arms[0].body)), - _ => None, - } - } else { - None + let exprs = if let PatKind::Expr(PatExprKind::Lit { lit, .. }) = arms[0].pat.kind { + match lit.node { + LitKind::Bool(true) => Some((arms[0].body, arms[1].body)), + LitKind::Bool(false) => Some((arms[1].body, arms[0].body)), + _ => None, } } else { None diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 28e05c273d5c7..33a00e2d2518c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -311,7 +311,7 @@ impl<'a> NormalizedPat<'a> { ); Self::Tuple(None, pats) }, - PatKind::Expr(e) => match &e.kind { + PatKind::Expr(ref e) => match e { // TODO: Handle negative integers. They're currently treated as a wild match. PatExprKind::Lit { lit, negated: false } => match lit.node { LitKind::Str(sym, _) => Self::LitStr(sym), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs index 9f5b7c855a139..8dc690b826416 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr}; -use rustc_hir::{Arm, Expr, ExprKind, PatExpr, PatExprKind, LangItem, PatKind}; +use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatExprKind, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -85,10 +85,7 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<( }; for arm in arms { - if let PatKind::Expr(PatExpr { - kind: PatExprKind::Lit { lit, negated: false }, - .. - }) = arm.pat.kind + if let PatKind::Expr(PatExprKind::Lit { lit, negated: false }) = arm.pat.kind && let LitKind::Str(symbol, _) = lit.node && let input = symbol.as_str() && !case_check(input) diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs index 0d5575efc2209..6a57a149792fb 100644 --- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs @@ -193,7 +193,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { if let PatExprKind::Lit { lit: pat_spanned, negated: false, - } = &pat_expr_expr.kind + } = &pat_expr_expr { return pat_spanned.node == expr_spanned.node; } diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 4a5d3c516b880..e96a70344d374 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -34,13 +34,13 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) if let Arm { pat, guard: None, .. } = *arm { if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind { let lhs_const = if let Some(lhs) = lhs { - ConstEvalCtxt::new(cx).eval_pat_expr(lhs)? + ConstEvalCtxt::new(cx).eval_pat_expr(lhs.hir_id, &lhs.kind)? } else { let min_val_const = ty.numeric_min_val(cx.tcx)?; mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? }; let rhs_const = if let Some(rhs) = rhs { - ConstEvalCtxt::new(cx).eval_pat_expr(rhs)? + ConstEvalCtxt::new(cx).eval_pat_expr(rhs.hir_id, &rhs.kind)? } else { let max_val_const = ty.numeric_max_val(cx.tcx)?; mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? @@ -57,9 +57,9 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) }); } - if let PatKind::Expr(value) = pat.kind { + if let PatKind::Expr(value) = &pat.kind { let value = ConstEvalCtxt::new(cx) - .eval_pat_expr(value)? + .eval_pat_expr(pat.hir_id, value)? .int_value(cx.tcx, cx.typeck_results().node_type(pat.hir_id))?; return Some(SpannedRange { span: pat.span, diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index edac97344a03c..868644543cf53 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -74,8 +74,7 @@ fn find_match_true<'tcx>( span: Span, message: &'static str, ) { - if let PatKind::Expr(lit) = pat.kind - && let PatExprKind::Lit { lit, negated: false } = lit.kind + if let PatKind::Expr(PatExprKind::Lit { lit, negated: false }) = pat.kind && let LitKind::Bool(pat_is_true) = lit.node { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 38f876fed802e..178e0bbe42148 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -9,7 +9,7 @@ use rustc_arena::DroplessArena; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_pat}; -use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind}; +use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExprKind, PatKind, QPath, StmtKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef}; use rustc_span::{Span, sym}; @@ -126,10 +126,9 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp // scrutinee derives PartialEq and the pattern is a constant. let pat_ref_count = match pat.kind { // string literals are already a reference. - PatKind::Expr(PatExpr { - kind: PatExprKind::Lit { lit, negated: false }, - .. - }) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1, + PatKind::Expr(PatExprKind::Lit { lit, negated: false }) if lit.node.is_str() || lit.node.is_bytestr() => { + pat_ref_count + 1 + }, _ => pat_ref_count, }; // References are only implicitly added to the pattern, so no overflow here. diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs index 3834087f79779..1e0bd88f811cb 100644 --- a/src/tools/clippy/clippy_lints/src/string_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs @@ -171,7 +171,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr< return ControlFlow::Break(()); } if arm.pat.walk_short(|pat| match pat.kind { - PatKind::Expr(expr) if let PatExprKind::Lit { lit, negated: false } = expr.kind => { + PatKind::Expr(expr) if let PatExprKind::Lit { lit, negated: false } = expr => { if let LitKind::Char(_) = lit.node { set_char_spans.push(lit.span); } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4dcc8ac7fb0af..f5a0ac726bc65 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -644,11 +644,18 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } fn pat_expr(&self, lit: &Binding<&hir::PatExpr<'_>>) { - let kind = |kind| chain!(self, "let PatExprKind::{kind} = {lit}.kind"); + let kind = &lit.value.kind; + bind!(self, kind); + chain!(self, "{kind} = &{lit}.kind"); + self.pat_expr_kind(kind); + } + + fn pat_expr_kind(&self, lit: &Binding<&PatExprKind<'_>>) { + let kind = |kind| chain!(self, "let PatExprKind::{kind} = {lit}"); macro_rules! kind { ($($t:tt)*) => (kind(format_args!($($t)*))); } - match lit.value.kind { + match *lit.value { PatExprKind::Lit { lit, negated } => { bind!(self, lit); bind!(self, negated); @@ -739,10 +746,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.pat(pat); self.expr(cond); }, - PatKind::Expr(lit_expr) => { + PatKind::Expr(ref lit_expr) => { bind!(self, lit_expr); - kind!("Expr({lit_expr})"); - self.pat_expr(lit_expr); + kind!("Expr(ref {lit_expr})"); + self.pat_expr_kind(lit_expr); }, PatKind::Range(start, end, end_kind) => { opt_bind!(self, start, end); diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index d46beddf73124..3f978680eab26 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -12,7 +12,9 @@ use rustc_apfloat::ieee::{Half, Quad}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp, PatExpr, PatExprKind}; +use rustc_hir::{ + BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExprKind, QPath, UnOp, +}; use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; @@ -441,19 +443,19 @@ impl<'tcx> ConstEvalCtxt<'tcx> { } } - pub fn eval_pat_expr(&self, pat_expr: &PatExpr<'_>) -> Option> { - match &pat_expr.kind { + pub fn eval_pat_expr(&self, hir_id: HirId, pat_expr: &PatExprKind<'_>) -> Option> { + match &pat_expr { PatExprKind::Lit { lit, negated } => { - let ty = self.typeck.node_type_opt(pat_expr.hir_id); + let ty = self.typeck.node_type_opt(hir_id); let val = lit_to_mir_constant(&lit.node, ty); if *negated { self.constant_negate(&val, ty?) } else { Some(val) } - } - PatExprKind::ConstBlock(ConstBlock { body, ..}) => self.expr(self.tcx.hir().body(*body).value), - PatExprKind::Path(qpath) => self.qpath(qpath, pat_expr.hir_id), + }, + PatExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(*body).value), + PatExprKind::Path(qpath) => self.qpath(qpath, hir_id), } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a1c48d5c36cf4..b0510064edd7f 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, - Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, + Pat, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty, TyKind, }; use rustc_lexer::{TokenKind, tokenize}; @@ -489,8 +489,8 @@ impl HirEqInterExpr<'_, '_, '_> { li.name == ri.name && self.eq_pat(lp, rp) } - fn eq_pat_expr(&mut self, left: &PatExpr<'_>, right: &PatExpr<'_>) -> bool { - match (&left.kind, &right.kind) { + fn eq_pat_expr(&mut self, left: &PatExprKind<'_>, right: &PatExprKind<'_>) -> bool { + match (left, right) { ( &PatExprKind::Lit { lit: left, @@ -525,11 +525,11 @@ impl HirEqInterExpr<'_, '_, '_> { eq }, (PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r), - (&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r), + (PatKind::Expr(l), PatKind::Expr(r)) => self.eq_pat_expr(l, r), (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)), (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => { - both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(a, b)) - && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b)) + both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(&a.kind, &b.kind)) + && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(&a.kind, &b.kind)) && (li == ri) }, (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re), @@ -1091,9 +1091,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); } - pub fn hash_pat_expr(&mut self, lit: &PatExpr<'_>) { - std::mem::discriminant(&lit.kind).hash(&mut self.s); - match &lit.kind { + pub fn hash_pat_expr(&mut self, kind: &PatExprKind<'_>) { + std::mem::discriminant(kind).hash(&mut self.s); + match kind { PatExprKind::Lit { lit, negated } => { lit.node.hash(&mut self.s); negated.hash(&mut self.s); @@ -1114,7 +1114,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat), - PatKind::Expr(expr) => self.hash_pat_expr(expr), + PatKind::Expr(ref expr) => self.hash_pat_expr(expr), PatKind::Or(pats) => { for pat in pats { self.hash_pat(pat); @@ -1123,10 +1123,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { PatKind::Path(ref qpath) => self.hash_qpath(qpath), PatKind::Range(s, e, i) => { if let Some(s) = s { - self.hash_pat_expr(s); + self.hash_pat_expr(&s.kind); } if let Some(e) = e { - self.hash_pat_expr(e); + self.hash_pat_expr(&e.kind); } std::mem::discriminant(&i).hash(&mut self.s); }, diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout index 8ffdf8862027b..011dabb814208 100644 --- a/src/tools/clippy/tests/ui/author/if.stdout +++ b/src/tools/clippy/tests/ui/author/if.stdout @@ -30,8 +30,8 @@ if let StmtKind::Let(local) = stmt.kind } if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind && let ExprKind::Let(let_expr) = cond.kind - && let PatKind::Expr(lit_expr) = let_expr.pat.kind - && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind + && let PatKind::Expr(ref lit_expr) = let_expr.pat.kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr && let LitKind::Bool(true) = lit.node && let ExprKind::Path(ref qpath) = let_expr.init.kind && match_qpath(qpath, &["a"]) diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout index c94eb171f52b9..91d02101d4612 100644 --- a/src/tools/clippy/tests/ui/author/loop.stdout +++ b/src/tools/clippy/tests/ui/author/loop.stdout @@ -76,8 +76,8 @@ if let Some(higher::While { condition: condition, body: body }) = higher::While: // report your lint here } if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr) - && let PatKind::Expr(lit_expr) = let_pat.kind - && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind + && let PatKind::Expr(ref lit_expr) = let_pat.kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr && let LitKind::Bool(true) = lit.node && let ExprKind::Path(ref qpath) = let_expr.kind && match_qpath(qpath, &["a"]) diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout index acb3b140dfa13..6a47f96d87701 100644 --- a/src/tools/clippy/tests/ui/author/matches.stdout +++ b/src/tools/clippy/tests/ui/author/matches.stdout @@ -4,14 +4,14 @@ if let StmtKind::Let(local) = stmt.kind && let ExprKind::Lit(ref lit) = scrutinee.kind && let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node && arms.len() == 3 - && let PatKind::Expr(lit_expr) = arms[0].pat.kind - && let PatExprKind::Lit{ref lit1, negated } = lit_expr.kind + && let PatKind::Expr(ref lit_expr) = arms[0].pat.kind + && let PatExprKind::Lit{ref lit1, negated } = lit_expr && let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node && arms[0].guard.is_none() && let ExprKind::Lit(ref lit2) = arms[0].body.kind && let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node - && let PatKind::Expr(lit_expr1) = arms[1].pat.kind - && let PatExprKind::Lit{ref lit3, negated1 } = lit_expr1.kind + && let PatKind::Expr(ref lit_expr1) = arms[1].pat.kind + && let PatExprKind::Lit{ref lit3, negated1 } = lit_expr1 && let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node && arms[1].guard.is_none() && let ExprKind::Block(block, None) = arms[1].body.kind diff --git a/src/tools/clippy/tests/ui/author/struct.stdout b/src/tools/clippy/tests/ui/author/struct.stdout index b66bbccb3cf1b..fe4794918cccb 100644 --- a/src/tools/clippy/tests/ui/author/struct.stdout +++ b/src/tools/clippy/tests/ui/author/struct.stdout @@ -23,8 +23,8 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind && match_qpath(qpath, &["Test"]) && fields.len() == 1 && fields[0].ident.as_str() == "field" - && let PatKind::Expr(lit_expr) = fields[0].pat.kind - && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind + && let PatKind::Expr(ref lit_expr) = fields[0].pat.kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node && arm.guard.is_none() && let ExprKind::Block(block, None) = arm.body.kind @@ -36,8 +36,8 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind && match_qpath(qpath, &["TestTuple"]) && fields.len() == 1 - && let PatKind::Expr(lit_expr) = fields[0].kind - && let PatExprKind::Lit{ref lit, negated } = lit_expr.kind + && let PatKind::Expr(ref lit_expr) = fields[0].kind + && let PatExprKind::Lit{ref lit, negated } = lit_expr && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node && arm.guard.is_none() && let ExprKind::Block(block, None) = arm.body.kind