mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
Exhaustively handle expressions in patterns
This commit is contained in:
parent
5df69191cb
commit
c9365dd09f
@ -102,17 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
let kind = match &e.kind {
|
let kind = match &e.kind {
|
||||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||||
ExprKind::ConstBlock(c) => {
|
ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),
|
||||||
let c = self.with_new_scopes(c.value.span, |this| {
|
|
||||||
let def_id = this.local_def_id(c.id);
|
|
||||||
hir::ConstBlock {
|
|
||||||
def_id,
|
|
||||||
hir_id: this.lower_node_id(c.id),
|
|
||||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
hir::ExprKind::ConstBlock(c)
|
|
||||||
}
|
|
||||||
ExprKind::Repeat(expr, count) => {
|
ExprKind::Repeat(expr, count) => {
|
||||||
let expr = self.lower_expr(expr);
|
let expr = self.lower_expr(expr);
|
||||||
let count = self.lower_array_length_to_const_arg(count);
|
let count = self.lower_array_length_to_const_arg(count);
|
||||||
@ -153,18 +143,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let ohs = self.lower_expr(ohs);
|
let ohs = self.lower_expr(ohs);
|
||||||
hir::ExprKind::Unary(op, ohs)
|
hir::ExprKind::Unary(op, ohs)
|
||||||
}
|
}
|
||||||
ExprKind::Lit(token_lit) => {
|
ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
|
||||||
let lit_kind = match LitKind::from_token_lit(*token_lit) {
|
|
||||||
Ok(lit_kind) => lit_kind,
|
|
||||||
Err(err) => {
|
|
||||||
let guar =
|
|
||||||
report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span);
|
|
||||||
LitKind::Err(guar)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));
|
|
||||||
hir::ExprKind::Lit(lit)
|
|
||||||
}
|
|
||||||
ExprKind::IncludedBytes(bytes) => {
|
ExprKind::IncludedBytes(bytes) => {
|
||||||
let lit = self.arena.alloc(respan(
|
let lit = self.arena.alloc(respan(
|
||||||
self.lower_span(e.span),
|
self.lower_span(e.span),
|
||||||
@ -403,6 +382,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
|
||||||
|
self.with_new_scopes(c.value.span, |this| {
|
||||||
|
let def_id = this.local_def_id(c.id);
|
||||||
|
hir::ConstBlock {
|
||||||
|
def_id,
|
||||||
|
hir_id: this.lower_node_id(c.id),
|
||||||
|
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lower_lit(
|
||||||
|
&mut self,
|
||||||
|
token_lit: &token::Lit,
|
||||||
|
span: Span,
|
||||||
|
) -> &'hir Spanned<LitKind> {
|
||||||
|
let lit_kind = match LitKind::from_token_lit(*token_lit) {
|
||||||
|
Ok(lit_kind) => lit_kind,
|
||||||
|
Err(err) => {
|
||||||
|
let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span);
|
||||||
|
LitKind::Err(guar)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.arena.alloc(respan(self.lower_span(span), lit_kind))
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
|
fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
|
||||||
match u {
|
match u {
|
||||||
UnOp::Deref => hir::UnOp::Deref,
|
UnOp::Deref => hir::UnOp::Deref,
|
||||||
|
@ -209,6 +209,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_pat_expr(&mut self, expr: &'hir PatExpr<'hir>) {
|
||||||
|
self.insert(expr.span, expr.hir_id, Node::PatExpr(expr));
|
||||||
|
|
||||||
|
self.with_parent(expr.hir_id, |this| {
|
||||||
|
intravisit::walk_pat_expr(this, expr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) {
|
fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) {
|
||||||
self.insert(field.span, field.hir_id, Node::PatField(field));
|
self.insert(field.span, field.hir_id, Node::PatField(field));
|
||||||
self.with_parent(field.hir_id, |this| {
|
self.with_parent(field.hir_id, |this| {
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
#![feature(assert_matches)]
|
#![feature(assert_matches)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(if_let_guard)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
#![warn(unreachable_pub)]
|
#![warn(unreachable_pub)]
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_middle::span_bug;
|
||||||
|
use rustc_span::source_map::{Spanned, respan};
|
||||||
use rustc_span::{Ident, Span};
|
use rustc_span::{Ident, Span};
|
||||||
|
|
||||||
use super::errors::{
|
use super::errors::{
|
||||||
@ -367,24 +370,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// }
|
// }
|
||||||
// m!(S);
|
// m!(S);
|
||||||
// ```
|
// ```
|
||||||
fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> {
|
fn lower_expr_within_pat(
|
||||||
match &expr.kind {
|
&mut self,
|
||||||
ExprKind::Lit(..)
|
expr: &Expr,
|
||||||
| ExprKind::ConstBlock(..)
|
allow_paths: bool,
|
||||||
| ExprKind::IncludedBytes(..)
|
) -> &'hir hir::PatExpr<'hir> {
|
||||||
| ExprKind::Err(_)
|
let err = |guar| hir::PatExprKind::Lit {
|
||||||
| ExprKind::Dummy => {}
|
lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))),
|
||||||
ExprKind::Path(..) if allow_paths => {}
|
negated: false,
|
||||||
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
|
};
|
||||||
|
let kind = match &expr.kind {
|
||||||
|
ExprKind::Lit(lit) => {
|
||||||
|
hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false }
|
||||||
|
}
|
||||||
|
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
|
||||||
|
ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit {
|
||||||
|
lit: self.arena.alloc(respan(
|
||||||
|
self.lower_span(expr.span),
|
||||||
|
LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked),
|
||||||
|
)),
|
||||||
|
negated: false,
|
||||||
|
},
|
||||||
|
ExprKind::Err(guar) => err(*guar),
|
||||||
|
ExprKind::Dummy => span_bug!(expr.span, "lowered ExprKind::Dummy"),
|
||||||
|
ExprKind::Path(qself, path) if allow_paths => hir::PatExprKind::Path(self.lower_qpath(
|
||||||
|
expr.id,
|
||||||
|
qself,
|
||||||
|
path,
|
||||||
|
ParamMode::Optional,
|
||||||
|
AllowReturnTypeNotation::No,
|
||||||
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
ExprKind::Unary(UnOp::Neg, inner) if let ExprKind::Lit(lit) = &inner.kind => {
|
||||||
|
hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: true }
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let pattern_from_macro = expr.is_approximately_pattern();
|
let pattern_from_macro = expr.is_approximately_pattern();
|
||||||
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
|
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
pattern_from_macro_note: pattern_from_macro,
|
pattern_from_macro_note: pattern_from_macro,
|
||||||
});
|
});
|
||||||
return self.arena.alloc(self.expr_err(expr.span, guar));
|
err(guar)
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
self.lower_expr(expr)
|
self.arena.alloc(hir::PatExpr {
|
||||||
|
hir_id: self.lower_node_id(expr.id),
|
||||||
|
span: expr.span,
|
||||||
|
kind,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1519,6 +1519,26 @@ impl fmt::Debug for DotDotPos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
|
pub struct PatExpr<'hir> {
|
||||||
|
pub hir_id: HirId,
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: PatExprKind<'hir>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
|
pub enum PatExprKind<'hir> {
|
||||||
|
Lit {
|
||||||
|
lit: &'hir Lit,
|
||||||
|
// FIXME: move this into `Lit` and handle negated literal expressions
|
||||||
|
// once instead of matching on unop neg expressions everywhere.
|
||||||
|
negated: bool,
|
||||||
|
},
|
||||||
|
ConstBlock(ConstBlock),
|
||||||
|
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
|
||||||
|
Path(QPath<'hir>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum PatKind<'hir> {
|
pub enum PatKind<'hir> {
|
||||||
/// Represents a wildcard pattern (i.e., `_`).
|
/// Represents a wildcard pattern (i.e., `_`).
|
||||||
@ -1564,13 +1584,13 @@ pub enum PatKind<'hir> {
|
|||||||
Ref(&'hir Pat<'hir>, Mutability),
|
Ref(&'hir Pat<'hir>, Mutability),
|
||||||
|
|
||||||
/// A literal.
|
/// A literal.
|
||||||
Lit(&'hir Expr<'hir>),
|
Lit(&'hir PatExpr<'hir>),
|
||||||
|
|
||||||
/// A guard pattern (e.g., `x if guard(x)`).
|
/// A guard pattern (e.g., `x if guard(x)`).
|
||||||
Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
|
Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
|
||||||
|
|
||||||
/// A range pattern (e.g., `1..=2` or `1..2`).
|
/// A range pattern (e.g., `1..=2` or `1..2`).
|
||||||
Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
|
Range(Option<&'hir PatExpr<'hir>>, Option<&'hir PatExpr<'hir>>, RangeEnd),
|
||||||
|
|
||||||
/// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
|
/// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
|
||||||
///
|
///
|
||||||
@ -4144,6 +4164,10 @@ pub enum Node<'hir> {
|
|||||||
OpaqueTy(&'hir OpaqueTy<'hir>),
|
OpaqueTy(&'hir OpaqueTy<'hir>),
|
||||||
Pat(&'hir Pat<'hir>),
|
Pat(&'hir Pat<'hir>),
|
||||||
PatField(&'hir PatField<'hir>),
|
PatField(&'hir PatField<'hir>),
|
||||||
|
/// Needed as its own node with its own HirId for tracking
|
||||||
|
/// the unadjusted type of literals within patterns
|
||||||
|
/// (e.g. byte str literals not being of slice type).
|
||||||
|
PatExpr(&'hir PatExpr<'hir>),
|
||||||
Arm(&'hir Arm<'hir>),
|
Arm(&'hir Arm<'hir>),
|
||||||
Block(&'hir Block<'hir>),
|
Block(&'hir Block<'hir>),
|
||||||
LetStmt(&'hir LetStmt<'hir>),
|
LetStmt(&'hir LetStmt<'hir>),
|
||||||
@ -4200,6 +4224,7 @@ impl<'hir> Node<'hir> {
|
|||||||
| Node::Block(..)
|
| Node::Block(..)
|
||||||
| Node::Ctor(..)
|
| Node::Ctor(..)
|
||||||
| Node::Pat(..)
|
| Node::Pat(..)
|
||||||
|
| Node::PatExpr(..)
|
||||||
| Node::Arm(..)
|
| Node::Arm(..)
|
||||||
| Node::LetStmt(..)
|
| Node::LetStmt(..)
|
||||||
| Node::Crate(..)
|
| Node::Crate(..)
|
||||||
|
@ -342,6 +342,9 @@ pub trait Visitor<'v>: Sized {
|
|||||||
fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
|
fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
|
||||||
walk_pat_field(self, f)
|
walk_pat_field(self, f)
|
||||||
}
|
}
|
||||||
|
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
|
||||||
|
walk_pat_expr(self, expr)
|
||||||
|
}
|
||||||
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
|
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
|
||||||
walk_anon_const(self, c)
|
walk_anon_const(self, c)
|
||||||
}
|
}
|
||||||
@ -685,10 +688,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
|
|||||||
try_visit!(visitor.visit_ident(ident));
|
try_visit!(visitor.visit_ident(ident));
|
||||||
visit_opt!(visitor, visit_pat, optional_subpattern);
|
visit_opt!(visitor, visit_pat, optional_subpattern);
|
||||||
}
|
}
|
||||||
PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)),
|
PatKind::Lit(ref expression) => try_visit!(visitor.visit_pat_expr(expression)),
|
||||||
PatKind::Range(ref lower_bound, ref upper_bound, _) => {
|
PatKind::Range(ref lower_bound, ref upper_bound, _) => {
|
||||||
visit_opt!(visitor, visit_expr, lower_bound);
|
visit_opt!(visitor, visit_pat_expr, lower_bound);
|
||||||
visit_opt!(visitor, visit_expr, upper_bound);
|
visit_opt!(visitor, visit_pat_expr, upper_bound);
|
||||||
}
|
}
|
||||||
PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
|
PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
|
||||||
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
|
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
|
||||||
@ -710,6 +713,15 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
|
|||||||
visitor.visit_pat(field.pat)
|
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 {
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
|
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
|
||||||
try_visit!(visitor.visit_id(constant.hir_id));
|
try_visit!(visitor.visit_id(constant.hir_id));
|
||||||
visitor.visit_nested_body(constant.body)
|
visitor.visit_nested_body(constant.body)
|
||||||
|
@ -2449,17 +2449,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
Ty::new_error(tcx, err)
|
Ty::new_error(tcx, err)
|
||||||
}
|
}
|
||||||
hir::PatKind::Range(start, end, include_end) => {
|
hir::PatKind::Range(start, end, include_end) => {
|
||||||
let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
|
let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> {
|
||||||
let (expr, neg) = match expr.kind {
|
let (c, c_ty) = match expr.kind {
|
||||||
hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
|
hir::PatExprKind::Lit { lit, negated } => {
|
||||||
(negated, Some((expr.hir_id, expr.span)))
|
|
||||||
}
|
|
||||||
_ => (expr, None),
|
|
||||||
};
|
|
||||||
let (c, c_ty) = match &expr.kind {
|
|
||||||
hir::ExprKind::Lit(lit) => {
|
|
||||||
let lit_input =
|
let lit_input =
|
||||||
LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
|
LitToConstInput { lit: &lit.node, ty, neg: negated };
|
||||||
let ct = match tcx.lit_to_const(lit_input) {
|
let ct = match tcx.lit_to_const(lit_input) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(LitToConstError::Reported(err)) => {
|
Err(LitToConstError::Reported(err)) => {
|
||||||
@ -2470,23 +2464,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
(ct, ty)
|
(ct, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
hir::PatExprKind::Path(hir::QPath::Resolved(
|
||||||
_,
|
_,
|
||||||
path @ &hir::Path {
|
path @ &hir::Path {
|
||||||
res: Res::Def(DefKind::ConstParam, def_id),
|
res: Res::Def(DefKind::ConstParam, def_id),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
)) => {
|
)) => {
|
||||||
let _ = self.prohibit_generic_args(
|
match self.prohibit_generic_args(
|
||||||
path.segments.iter(),
|
path.segments.iter(),
|
||||||
GenericsArgsErrExtend::Param(def_id),
|
GenericsArgsErrExtend::Param(def_id),
|
||||||
);
|
) {
|
||||||
let ty = tcx
|
Ok(()) => {
|
||||||
.type_of(def_id)
|
let ty = tcx
|
||||||
.no_bound_vars()
|
.type_of(def_id)
|
||||||
.expect("const parameter types cannot be generic");
|
.no_bound_vars()
|
||||||
let ct = self.lower_const_param(def_id, expr.hir_id);
|
.expect("const parameter types cannot be generic");
|
||||||
(ct, ty)
|
let ct = self.lower_const_param(def_id, expr.hir_id);
|
||||||
|
(ct, ty)
|
||||||
|
}
|
||||||
|
Err(guar) => (
|
||||||
|
ty::Const::new_error(tcx, guar),
|
||||||
|
Ty::new_error(tcx, guar),
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
@ -2497,9 +2498,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.record_ty(expr.hir_id, c_ty, expr.span);
|
self.record_ty(expr.hir_id, c_ty, expr.span);
|
||||||
if let Some((id, span)) = neg {
|
|
||||||
self.record_ty(id, c_ty, span);
|
|
||||||
}
|
|
||||||
c
|
c
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,6 +199,7 @@ impl<'a> State<'a> {
|
|||||||
Node::OpaqueTy(o) => self.print_opaque_ty(o),
|
Node::OpaqueTy(o) => self.print_opaque_ty(o),
|
||||||
Node::Pat(a) => self.print_pat(a),
|
Node::Pat(a) => self.print_pat(a),
|
||||||
Node::PatField(a) => self.print_patfield(a),
|
Node::PatField(a) => self.print_patfield(a),
|
||||||
|
Node::PatExpr(a) => self.print_pat_expr(a),
|
||||||
Node::Arm(a) => self.print_arm(a),
|
Node::Arm(a) => self.print_arm(a),
|
||||||
Node::Infer(_) => self.word("_"),
|
Node::Infer(_) => self.word("_"),
|
||||||
Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
|
Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
|
||||||
@ -1849,6 +1850,19 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_pat_expr(&mut self, expr: &hir::PatExpr<'_>) {
|
||||||
|
match &expr.kind {
|
||||||
|
hir::PatExprKind::Lit { lit, negated } => {
|
||||||
|
if *negated {
|
||||||
|
self.word("-");
|
||||||
|
}
|
||||||
|
self.print_literal(lit);
|
||||||
|
}
|
||||||
|
hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
|
||||||
|
hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn print_pat(&mut self, pat: &hir::Pat<'_>) {
|
fn print_pat(&mut self, pat: &hir::Pat<'_>) {
|
||||||
self.maybe_print_comment(pat.span.lo());
|
self.maybe_print_comment(pat.span.lo());
|
||||||
self.ann.pre(self, AnnNode::Pat(pat));
|
self.ann.pre(self, AnnNode::Pat(pat));
|
||||||
@ -1966,17 +1980,17 @@ impl<'a> State<'a> {
|
|||||||
self.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Lit(e) => self.print_expr(e),
|
PatKind::Lit(e) => self.print_pat_expr(e),
|
||||||
PatKind::Range(begin, end, end_kind) => {
|
PatKind::Range(begin, end, end_kind) => {
|
||||||
if let Some(expr) = begin {
|
if let Some(expr) = begin {
|
||||||
self.print_expr(expr);
|
self.print_pat_expr(expr);
|
||||||
}
|
}
|
||||||
match end_kind {
|
match end_kind {
|
||||||
RangeEnd::Included => self.word("..."),
|
RangeEnd::Included => self.word("..."),
|
||||||
RangeEnd::Excluded => self.word(".."),
|
RangeEnd::Excluded => self.word(".."),
|
||||||
}
|
}
|
||||||
if let Some(expr) = end {
|
if let Some(expr) = end {
|
||||||
self.print_expr(expr);
|
self.print_pat_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Slice(before, slice, after) => {
|
PatKind::Slice(before, slice, after) => {
|
||||||
|
@ -430,6 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
| hir::Node::AssocItemConstraint(_)
|
| hir::Node::AssocItemConstraint(_)
|
||||||
| hir::Node::TraitRef(_)
|
| hir::Node::TraitRef(_)
|
||||||
| hir::Node::PatField(_)
|
| hir::Node::PatField(_)
|
||||||
|
| hir::Node::PatExpr(_)
|
||||||
| hir::Node::LetStmt(_)
|
| hir::Node::LetStmt(_)
|
||||||
| hir::Node::Synthetic
|
| hir::Node::Synthetic
|
||||||
| hir::Node::Err(_)
|
| hir::Node::Err(_)
|
||||||
@ -1796,7 +1797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_const_block(
|
pub(super) fn check_expr_const_block(
|
||||||
&self,
|
&self,
|
||||||
block: &'tcx hir::ConstBlock,
|
block: &'tcx hir::ConstBlock,
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
|
@ -1039,6 +1039,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
def_id,
|
def_id,
|
||||||
span,
|
span,
|
||||||
),
|
),
|
||||||
|
Res::Err => {
|
||||||
|
return (
|
||||||
|
Ty::new_error(
|
||||||
|
tcx,
|
||||||
|
tcx.dcx().span_delayed_bug(span, "could not resolve path {:?}"),
|
||||||
|
),
|
||||||
|
res,
|
||||||
|
);
|
||||||
|
}
|
||||||
_ => bug!("instantiate_value_path on {:?}", res),
|
_ => bug!("instantiate_value_path on {:?}", res),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,6 +170,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
|
| hir::Node::PatExpr(&hir::PatExpr {
|
||||||
|
kind: hir::PatExprKind::Path(QPath::TypeRelative(rcvr, segment)),
|
||||||
|
span,
|
||||||
|
..
|
||||||
|
})
|
||||||
| hir::Node::Pat(&hir::Pat {
|
| hir::Node::Pat(&hir::Pat {
|
||||||
kind:
|
kind:
|
||||||
hir::PatKind::Path(QPath::TypeRelative(rcvr, segment))
|
hir::PatKind::Path(QPath::TypeRelative(rcvr, segment))
|
||||||
|
@ -30,6 +30,7 @@ use tracing::{debug, instrument, trace};
|
|||||||
use ty::VariantDef;
|
use ty::VariantDef;
|
||||||
|
|
||||||
use super::report_unexpected_variant_res;
|
use super::report_unexpected_variant_res;
|
||||||
|
use crate::expectation::Expectation;
|
||||||
use crate::gather_locals::DeclOrigin;
|
use crate::gather_locals::DeclOrigin;
|
||||||
use crate::{FnCtxt, LoweredTy, errors};
|
use crate::{FnCtxt, LoweredTy, errors};
|
||||||
|
|
||||||
@ -398,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
|
// 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.
|
// Call `resolve_vars_if_possible` here for inline const blocks.
|
||||||
PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
|
PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
|
||||||
ty::Ref(..) => AdjustMode::Pass,
|
ty::Ref(..) => AdjustMode::Pass,
|
||||||
_ => AdjustMode::Peel,
|
_ => AdjustMode::Peel,
|
||||||
},
|
},
|
||||||
@ -493,10 +494,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
(expected, def_br, max_ref_mutbl)
|
(expected, def_br, max_ref_mutbl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> {
|
||||||
|
let ty = match <.kind {
|
||||||
|
rustc_hir::PatExprKind::Lit { lit, .. } => {
|
||||||
|
self.check_expr_lit(lit, Expectation::NoExpectation)
|
||||||
|
}
|
||||||
|
rustc_hir::PatExprKind::ConstBlock(c) => {
|
||||||
|
self.check_expr_const_block(c, Expectation::NoExpectation)
|
||||||
|
}
|
||||||
|
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.write_ty(lt.hir_id, ty);
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
|
||||||
fn check_pat_lit(
|
fn check_pat_lit(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
lt: &hir::Expr<'tcx>,
|
lt: &hir::PatExpr<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
ti: &TopInfo<'tcx>,
|
ti: &TopInfo<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
@ -507,7 +526,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// Byte string patterns behave the same way as array patterns
|
// Byte string patterns behave the same way as array patterns
|
||||||
// They can denote both statically and dynamically-sized byte arrays.
|
// They can denote both statically and dynamically-sized byte arrays.
|
||||||
let mut pat_ty = ty;
|
let mut pat_ty = ty;
|
||||||
if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
|
if let hir::PatExprKind::Lit {
|
||||||
|
lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
|
||||||
|
} = lt.kind
|
||||||
|
{
|
||||||
let expected = self.structurally_resolve_type(span, expected);
|
let expected = self.structurally_resolve_type(span, expected);
|
||||||
if let ty::Ref(_, inner_ty, _) = *expected.kind()
|
if let ty::Ref(_, inner_ty, _) = *expected.kind()
|
||||||
&& self.try_structurally_resolve_type(span, inner_ty).is_slice()
|
&& self.try_structurally_resolve_type(span, inner_ty).is_slice()
|
||||||
@ -524,7 +546,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.tcx.features().string_deref_patterns()
|
if self.tcx.features().string_deref_patterns()
|
||||||
&& let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind
|
&& let hir::PatExprKind::Lit {
|
||||||
|
lit: Spanned { node: ast::LitKind::Str(..), .. }, ..
|
||||||
|
} = lt.kind
|
||||||
{
|
{
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let expected = self.resolve_vars_if_possible(expected);
|
let expected = self.resolve_vars_if_possible(expected);
|
||||||
@ -565,15 +589,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
fn check_pat_range(
|
fn check_pat_range(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
lhs: Option<&'tcx hir::Expr<'tcx>>,
|
lhs: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
rhs: Option<&'tcx hir::Expr<'tcx>>,
|
rhs: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
ti: &TopInfo<'tcx>,
|
ti: &TopInfo<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
|
let calc_side = |opt_expr: Option<&'tcx hir::PatExpr<'tcx>>| match opt_expr {
|
||||||
None => None,
|
None => None,
|
||||||
Some(expr) => {
|
Some(expr) => {
|
||||||
let ty = self.check_expr(expr);
|
let ty = self.check_pat_expr_unadjusted(expr);
|
||||||
// Check that the end-point is possibly of numeric or char type.
|
// Check that the end-point is possibly of numeric or char type.
|
||||||
// The early check here is not for correctness, but rather better
|
// The early check here is not for correctness, but rather better
|
||||||
// diagnostics (e.g. when `&str` is being matched, `expected` will
|
// diagnostics (e.g. when `&str` is being matched, `expected` will
|
||||||
@ -1813,9 +1837,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
} else if inexistent_fields.len() == 1 {
|
} else if inexistent_fields.len() == 1 {
|
||||||
match pat_field.pat.kind {
|
match pat_field.pat.kind {
|
||||||
PatKind::Lit(expr)
|
PatKind::Lit(_)
|
||||||
if !self.may_coerce(
|
if !self.may_coerce(
|
||||||
self.typeck_results.borrow().expr_ty(expr),
|
self.typeck_results.borrow().node_type(pat_field.pat.hir_id),
|
||||||
self.field_ty(field.span, field_def, args),
|
self.field_ty(field.span, field_def, args),
|
||||||
) => {}
|
) => {}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -147,15 +147,16 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
|
|||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
|
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
|
||||||
}
|
}
|
||||||
hir::ExprKind::ConstBlock(anon_const) => {
|
|
||||||
let body = self.fcx.tcx.hir().body(anon_const.body);
|
|
||||||
self.visit_body(body);
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
intravisit::walk_expr(self, expr);
|
intravisit::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
|
||||||
|
let body = self.fcx.tcx.hir().body(c.body);
|
||||||
|
self.visit_body(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
@ -246,6 +246,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_const_block(&mut self, span: Span, anon_const: &hir::ConstBlock) {
|
||||||
|
self.visit_node_id(span, anon_const.hir_id);
|
||||||
|
|
||||||
|
let body = self.tcx().hir().body(anon_const.body);
|
||||||
|
self.visit_body(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -275,11 +282,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
|||||||
hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
|
hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
|
||||||
self.visit_field_id(e.hir_id);
|
self.visit_field_id(e.hir_id);
|
||||||
}
|
}
|
||||||
hir::ExprKind::ConstBlock(anon_const) => {
|
hir::ExprKind::ConstBlock(ref anon_const) => {
|
||||||
self.visit_node_id(e.span, anon_const.hir_id);
|
self.visit_const_block(e.span, anon_const);
|
||||||
|
|
||||||
let body = self.tcx().hir().body(anon_const.body);
|
|
||||||
self.visit_body(body);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -335,6 +339,14 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
|||||||
intravisit::walk_pat(self, p);
|
intravisit::walk_pat(self, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) {
|
||||||
|
self.visit_node_id(expr.span, expr.hir_id);
|
||||||
|
if let hir::PatExprKind::ConstBlock(c) = &expr.kind {
|
||||||
|
self.visit_const_block(expr.span, c);
|
||||||
|
}
|
||||||
|
intravisit::walk_pat_expr(self, expr);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) {
|
fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) {
|
||||||
intravisit::walk_local(self, l);
|
intravisit::walk_local(self, l);
|
||||||
let var_ty = self.fcx.local_ty(l.span, l.hir_id);
|
let var_ty = self.fcx.local_ty(l.span, l.hir_id);
|
||||||
|
@ -938,6 +938,7 @@ impl<'hir> Map<'hir> {
|
|||||||
Node::OpaqueTy(op) => op.span,
|
Node::OpaqueTy(op) => op.span,
|
||||||
Node::Pat(pat) => pat.span,
|
Node::Pat(pat) => pat.span,
|
||||||
Node::PatField(field) => field.span,
|
Node::PatField(field) => field.span,
|
||||||
|
Node::PatExpr(lit) => lit.span,
|
||||||
Node::Arm(arm) => arm.span,
|
Node::Arm(arm) => arm.span,
|
||||||
Node::Block(block) => block.span,
|
Node::Block(block) => block.span,
|
||||||
Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
|
Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
|
||||||
@ -1209,6 +1210,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||||||
Node::OpaqueTy(_) => node_str("opaque type"),
|
Node::OpaqueTy(_) => node_str("opaque type"),
|
||||||
Node::Pat(_) => node_str("pat"),
|
Node::Pat(_) => node_str("pat"),
|
||||||
Node::PatField(_) => node_str("pattern field"),
|
Node::PatField(_) => node_str("pattern field"),
|
||||||
|
Node::PatExpr(_) => node_str("pattern literal"),
|
||||||
Node::Param(_) => node_str("param"),
|
Node::Param(_) => node_str("param"),
|
||||||
Node::Arm(_) => node_str("arm"),
|
Node::Arm(_) => node_str("arm"),
|
||||||
Node::Block(_) => node_str("block"),
|
Node::Block(_) => node_str("block"),
|
||||||
|
@ -154,7 +154,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
fn lower_pattern_range_endpoint(
|
fn lower_pattern_range_endpoint(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Option<&'tcx hir::Expr<'tcx>>,
|
expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
|
(Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
|
||||||
ErrorGuaranteed,
|
ErrorGuaranteed,
|
||||||
@ -200,13 +200,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
/// This is only called when the range is already known to be malformed.
|
/// This is only called when the range is already known to be malformed.
|
||||||
fn error_on_literal_overflow(
|
fn error_on_literal_overflow(
|
||||||
&self,
|
&self,
|
||||||
expr: Option<&'tcx hir::Expr<'tcx>>,
|
expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
use hir::{ExprKind, UnOp};
|
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
|
|
||||||
let Some(mut expr) = expr else {
|
let Some(expr) = expr else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
let span = expr.span;
|
let span = expr.span;
|
||||||
@ -214,12 +213,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
// We need to inspect the original expression, because if we only inspect the output of
|
// We need to inspect the original expression, because if we only inspect the output of
|
||||||
// `eval_bits`, an overflowed value has already been wrapped around.
|
// `eval_bits`, an overflowed value has already been wrapped around.
|
||||||
// We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
|
// We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
|
||||||
let mut negated = false;
|
let hir::PatExprKind::Lit { lit, negated } = expr.kind else {
|
||||||
if let ExprKind::Unary(UnOp::Neg, sub_expr) = expr.kind {
|
|
||||||
negated = true;
|
|
||||||
expr = sub_expr;
|
|
||||||
}
|
|
||||||
let ExprKind::Lit(lit) = expr.kind else {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
let LitKind::Int(lit_val, _) = lit.node else {
|
let LitKind::Int(lit_val, _) = lit.node else {
|
||||||
@ -248,8 +242,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
fn lower_pattern_range(
|
fn lower_pattern_range(
|
||||||
&mut self,
|
&mut self,
|
||||||
lo_expr: Option<&'tcx hir::Expr<'tcx>>,
|
lo_expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
hi_expr: Option<&'tcx hir::Expr<'tcx>>,
|
hi_expr: Option<&'tcx hir::PatExpr<'tcx>>,
|
||||||
end: RangeEnd,
|
end: RangeEnd,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -662,25 +656,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
/// The special case for negation exists to allow things like `-128_i8`
|
/// 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
|
/// which would overflow if we tried to evaluate `128_i8` and then negate
|
||||||
/// afterwards.
|
/// afterwards.
|
||||||
fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
|
fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
|
||||||
let (lit, neg) = match expr.kind {
|
let (lit, neg) = match &expr.kind {
|
||||||
hir::ExprKind::Path(ref qpath) => {
|
hir::PatExprKind::Path(qpath) => {
|
||||||
return self.lower_path(qpath, expr.hir_id, expr.span).kind;
|
return self.lower_path(qpath, expr.hir_id, expr.span).kind;
|
||||||
}
|
}
|
||||||
hir::ExprKind::ConstBlock(ref anon_const) => {
|
hir::PatExprKind::ConstBlock(anon_const) => {
|
||||||
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
|
return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Lit(ref lit) => (lit, false),
|
hir::PatExprKind::Lit { lit, negated } => (lit, *negated),
|
||||||
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
|
|
||||||
let hir::ExprKind::Lit(ref lit) = expr.kind else {
|
|
||||||
span_bug!(expr.span, "not a literal: {:?}", expr);
|
|
||||||
};
|
|
||||||
(lit, true)
|
|
||||||
}
|
|
||||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let ct_ty = self.typeck_results.expr_ty(expr);
|
let ct_ty = self.typeck_results.node_type(expr.hir_id);
|
||||||
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
|
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
|
||||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||||
Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind,
|
Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind,
|
||||||
|
@ -3,8 +3,11 @@ use clippy_utils::numeric_literal;
|
|||||||
use clippy_utils::source::snippet_opt;
|
use clippy_utils::source::snippet_opt;
|
||||||
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
|
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
|
use rustc_hir::intravisit::{Visitor, walk_expr, walk_pat, walk_stmt};
|
||||||
use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr};
|
use rustc_hir::{
|
||||||
|
Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Pat, PatExpr, PatExprKind, PatKind, Stmt, StmtKind,
|
||||||
|
StructTailExpr,
|
||||||
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
|
use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
|
||||||
@ -219,6 +222,22 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> {
|
|||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_pat(&mut self, pat: &'tcx Pat<'_>) {
|
||||||
|
match pat.kind {
|
||||||
|
PatKind::Lit(&PatExpr {
|
||||||
|
hir_id,
|
||||||
|
kind: PatExprKind::Lit { lit, .. },
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
let ty = self.cx.typeck_results().node_type(hir_id);
|
||||||
|
self.check_lit(lit, ty, hir_id);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
walk_pat(self, pat)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
|
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
// we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
|
// we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
|
||||||
|
@ -8,8 +8,8 @@ use rustc_hir::def::Res;
|
|||||||
use rustc_hir::def_id::{DefId, DefIdSet};
|
use rustc_hir::def_id::{DefId, DefIdSet};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
|
AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
|
||||||
ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath,
|
ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatExprKind, PatKind, PathSegment, PrimTy,
|
||||||
TraitItemRef, TyKind,
|
QPath, TraitItemRef, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
|
use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
|
||||||
@ -163,7 +163,13 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
|
|||||||
if let ExprKind::Let(lt) = expr.kind
|
if let ExprKind::Let(lt) = expr.kind
|
||||||
&& match lt.pat.kind {
|
&& match lt.pat.kind {
|
||||||
PatKind::Slice([], None, []) => true,
|
PatKind::Slice([], None, []) => true,
|
||||||
PatKind::Lit(lit) if is_empty_string(lit) => true,
|
PatKind::Lit(lit) => match lit.kind {
|
||||||
|
PatExprKind::Lit { lit, .. } => match lit.node {
|
||||||
|
LitKind::Str(lit, _) => lit.as_str().is_empty(),
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
&& !expr.span.from_expansion()
|
&& !expr.span.from_expansion()
|
||||||
|
@ -7,7 +7,7 @@ use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operator
|
|||||||
use rustc_ast::LitKind::{Byte, Char};
|
use rustc_ast::LitKind::{Byte, Char};
|
||||||
use rustc_ast::ast::RangeLimits;
|
use rustc_ast::ast::RangeLimits;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd};
|
use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd, PatExpr, PatExprKind, Lit};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
|
|||||||
{
|
{
|
||||||
let arg = peel_ref_operators(cx, arg);
|
let arg = peel_ref_operators(cx, arg);
|
||||||
let ty_sugg = get_ty_sugg(cx, arg, start);
|
let ty_sugg = get_ty_sugg(cx, arg, start);
|
||||||
let range = check_range(start, end);
|
let range = check_expr_range(start, end);
|
||||||
check_is_ascii(cx, expr.span, arg, &range, ty_sugg);
|
check_is_ascii(cx, expr.span, arg, &range, ty_sugg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,19 +196,34 @@ fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
|
fn check_expr_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
|
||||||
if let ExprKind::Lit(start_lit) = &start.kind
|
if let ExprKind::Lit(start_lit) = &start.kind
|
||||||
&& let ExprKind::Lit(end_lit) = &end.kind
|
&& let ExprKind::Lit(end_lit) = &end.kind
|
||||||
{
|
{
|
||||||
match (&start_lit.node, &end_lit.node) {
|
check_lit_range(start_lit, end_lit)
|
||||||
(Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
|
|
||||||
(Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
|
|
||||||
(Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
|
|
||||||
(Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
|
|
||||||
(Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
|
|
||||||
_ => CharRange::Otherwise,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
CharRange::Otherwise
|
CharRange::Otherwise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn check_range(start: &PatExpr<'_>, end: &PatExpr<'_>) -> CharRange {
|
||||||
|
if let PatExprKind::Lit{ lit: start_lit, negated: false } = &start.kind
|
||||||
|
&& let PatExprKind::Lit{ lit: end_lit, negated: false } = &end.kind
|
||||||
|
{
|
||||||
|
check_lit_range(start_lit, end_lit)
|
||||||
|
} else {
|
||||||
|
CharRange::Otherwise
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_lit_range(start_lit: &Lit, end_lit: &Lit) -> CharRange {
|
||||||
|
match (&start_lit.node, &end_lit.node) {
|
||||||
|
(Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
|
||||||
|
(Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
|
||||||
|
(Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
|
||||||
|
(Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
|
||||||
|
(Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
|
||||||
|
_ => CharRange::Otherwise,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt;
|
|||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp};
|
use rustc_hir::{PatExpr, PatExprKind, PatKind, RangeEnd};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
@ -38,14 +38,13 @@ declare_clippy_lint! {
|
|||||||
}
|
}
|
||||||
declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
|
declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
|
||||||
|
|
||||||
fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
|
fn expr_as_i128(expr: &PatExpr<'_>) -> Option<i128> {
|
||||||
if let ExprKind::Unary(UnOp::Neg, expr) = expr.kind {
|
if let PatExprKind::Lit { lit, negated } = expr.kind
|
||||||
expr_as_i128(expr).map(|num| -num)
|
|
||||||
} else if let ExprKind::Lit(lit) = expr.kind
|
|
||||||
&& let LitKind::Int(num, _) = lit.node
|
&& let LitKind::Int(num, _) = lit.node
|
||||||
{
|
{
|
||||||
// Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now.
|
// Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now.
|
||||||
num.get().try_into().ok()
|
let n = i128::try_from(num.get()).ok()?;
|
||||||
|
Some(if negated { -n } else { n })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -58,7 +57,7 @@ struct Num {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Num {
|
impl Num {
|
||||||
fn new(expr: &Expr<'_>) -> Option<Self> {
|
fn new(expr: &PatExpr<'_>) -> Option<Self> {
|
||||||
Some(Self {
|
Some(Self {
|
||||||
val: expr_as_i128(expr)?,
|
val: expr_as_i128(expr)?,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
|
@ -4,7 +4,7 @@ use clippy_utils::source::{expr_block, snippet};
|
|||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, PatKind};
|
use rustc_hir::{Arm, Expr, PatExprKind, PatKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>]
|
|||||||
if arms.len() == 2 {
|
if arms.len() == 2 {
|
||||||
// no guards
|
// no guards
|
||||||
let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
|
let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
|
||||||
if let ExprKind::Lit(lit) = arm_bool.kind {
|
if let PatExprKind::Lit { lit, .. } = arm_bool.kind {
|
||||||
match lit.node {
|
match lit.node {
|
||||||
LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
|
LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
|
||||||
LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
|
LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
|
||||||
|
@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
|
|||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
|
use rustc_hir::{Arm, Expr, PatExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
|
||||||
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||||
use rustc_lint::{LateContext, LintContext};
|
use rustc_lint::{LateContext, LintContext};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
@ -313,7 +313,7 @@ impl<'a> NormalizedPat<'a> {
|
|||||||
},
|
},
|
||||||
PatKind::Lit(e) => match &e.kind {
|
PatKind::Lit(e) => match &e.kind {
|
||||||
// TODO: Handle negative integers. They're currently treated as a wild match.
|
// TODO: Handle negative integers. They're currently treated as a wild match.
|
||||||
ExprKind::Lit(lit) => match lit.node {
|
PatExprKind::Lit{ lit, negated: false } => match lit.node {
|
||||||
LitKind::Str(sym, _) => Self::LitStr(sym),
|
LitKind::Str(sym, _) => Self::LitStr(sym),
|
||||||
LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
|
LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
|
||||||
LitKind::Byte(val) => Self::LitInt(val.into()),
|
LitKind::Byte(val) => Self::LitInt(val.into()),
|
||||||
@ -330,7 +330,7 @@ impl<'a> NormalizedPat<'a> {
|
|||||||
let start = match start {
|
let start = match start {
|
||||||
None => 0,
|
None => 0,
|
||||||
Some(e) => match &e.kind {
|
Some(e) => match &e.kind {
|
||||||
ExprKind::Lit(lit) => match lit.node {
|
PatExprKind::Lit { lit, negated: false } => match lit.node {
|
||||||
LitKind::Int(val, _) => val.get(),
|
LitKind::Int(val, _) => val.get(),
|
||||||
LitKind::Char(val) => val.into(),
|
LitKind::Char(val) => val.into(),
|
||||||
LitKind::Byte(val) => val.into(),
|
LitKind::Byte(val) => val.into(),
|
||||||
@ -342,7 +342,7 @@ impl<'a> NormalizedPat<'a> {
|
|||||||
let (end, bounds) = match end {
|
let (end, bounds) = match end {
|
||||||
None => (u128::MAX, RangeEnd::Included),
|
None => (u128::MAX, RangeEnd::Included),
|
||||||
Some(e) => match &e.kind {
|
Some(e) => match &e.kind {
|
||||||
ExprKind::Lit(lit) => match lit.node {
|
PatExprKind::Lit { lit, negated: false } => match lit.node {
|
||||||
LitKind::Int(val, _) => (val.get(), bounds),
|
LitKind::Int(val, _) => (val.get(), bounds),
|
||||||
LitKind::Char(val) => (val.into(), bounds),
|
LitKind::Char(val) => (val.into(), bounds),
|
||||||
LitKind::Byte(val) => (val.into(), bounds),
|
LitKind::Byte(val) => (val.into(), bounds),
|
||||||
|
@ -5,7 +5,7 @@ use clippy_utils::ty::is_type_lang_item;
|
|||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::{Visitor, walk_expr};
|
use rustc_hir::intravisit::{Visitor, walk_expr};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind};
|
use rustc_hir::{Arm, Expr, ExprKind, PatExpr, PatExprKind, LangItem, PatKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -85,8 +85,8 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
|
|||||||
};
|
};
|
||||||
|
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
if let PatKind::Lit(Expr {
|
if let PatKind::Lit(PatExpr {
|
||||||
kind: ExprKind::Lit(lit),
|
kind: PatExprKind::Lit { lit, negated: false },
|
||||||
..
|
..
|
||||||
}) = arm.pat.kind
|
}) = arm.pat.kind
|
||||||
&& let LitKind::Str(symbol, _) = lit.node
|
&& let LitKind::Str(symbol, _) = lit.node
|
||||||
|
@ -8,7 +8,7 @@ use clippy_utils::{
|
|||||||
};
|
};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::OptionNone;
|
use rustc_hir::LangItem::OptionNone;
|
||||||
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath};
|
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatExprKind, PatKind, Path, QPath};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>
|
|||||||
},
|
},
|
||||||
// compare match_expr ty with RetTy in `fn foo() -> RetTy`
|
// compare match_expr ty with RetTy in `fn foo() -> RetTy`
|
||||||
Node::Item(item) => {
|
Node::Item(item) => {
|
||||||
if let ItemKind::Fn{ .. } = item.kind {
|
if let ItemKind::Fn { .. } = item.kind {
|
||||||
let output = cx
|
let output = cx
|
||||||
.tcx
|
.tcx
|
||||||
.fn_sig(item.owner_id)
|
.fn_sig(item.owner_id)
|
||||||
@ -189,8 +189,12 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// Example: `5 => 5`
|
// Example: `5 => 5`
|
||||||
(PatKind::Lit(pat_lit_expr), ExprKind::Lit(expr_spanned)) => {
|
(PatKind::Lit(pat_expr_expr), ExprKind::Lit(expr_spanned)) => {
|
||||||
if let ExprKind::Lit(pat_spanned) = &pat_lit_expr.kind {
|
if let PatExprKind::Lit {
|
||||||
|
lit: pat_spanned,
|
||||||
|
negated: false,
|
||||||
|
} = &pat_expr_expr.kind
|
||||||
|
{
|
||||||
return pat_spanned.node == expr_spanned.node;
|
return pat_spanned.node == expr_spanned.node;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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 Arm { pat, guard: None, .. } = *arm {
|
||||||
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
||||||
let lhs_const = if let Some(lhs) = lhs {
|
let lhs_const = if let Some(lhs) = lhs {
|
||||||
ConstEvalCtxt::new(cx).eval(lhs)?
|
ConstEvalCtxt::new(cx).eval_pat_expr(lhs)?
|
||||||
} else {
|
} else {
|
||||||
let min_val_const = ty.numeric_min_val(cx.tcx)?;
|
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))?
|
mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
|
||||||
};
|
};
|
||||||
let rhs_const = if let Some(rhs) = rhs {
|
let rhs_const = if let Some(rhs) = rhs {
|
||||||
ConstEvalCtxt::new(cx).eval(rhs)?
|
ConstEvalCtxt::new(cx).eval_pat_expr(rhs)?
|
||||||
} else {
|
} else {
|
||||||
let max_val_const = ty.numeric_max_val(cx.tcx)?;
|
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))?
|
mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
|
||||||
@ -58,7 +58,9 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let PatKind::Lit(value) = pat.kind {
|
if let PatKind::Lit(value) = pat.kind {
|
||||||
let value = ConstEvalCtxt::new(cx).eval_full_int(value)?;
|
let value = ConstEvalCtxt::new(cx)
|
||||||
|
.eval_pat_expr(value)?
|
||||||
|
.int_value(cx.tcx, cx.typeck_results().node_type(pat.hir_id))?;
|
||||||
return Some(SpannedRange {
|
return Some(SpannedRange {
|
||||||
span: pat.span,
|
span: pat.span,
|
||||||
node: (value, EndBound::Included(value)),
|
node: (value, EndBound::Included(value)),
|
||||||
|
@ -9,7 +9,7 @@ use rustc_ast::ast::LitKind;
|
|||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
|
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp, PatExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{self, GenericArgKind, Ty};
|
use rustc_middle::ty::{self, GenericArgKind, Ty};
|
||||||
use rustc_span::{Span, Symbol, sym};
|
use rustc_span::{Span, Symbol, sym};
|
||||||
@ -75,7 +75,7 @@ fn find_match_true<'tcx>(
|
|||||||
message: &'static str,
|
message: &'static str,
|
||||||
) {
|
) {
|
||||||
if let PatKind::Lit(lit) = pat.kind
|
if let PatKind::Lit(lit) = pat.kind
|
||||||
&& let ExprKind::Lit(lit) = lit.kind
|
&& let PatExprKind::Lit{ lit, negated: false } = lit.kind
|
||||||
&& let LitKind::Bool(pat_is_true) = lit.node
|
&& let LitKind::Bool(pat_is_true) = lit.node
|
||||||
{
|
{
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
|
@ -9,7 +9,7 @@ use rustc_arena::DroplessArena;
|
|||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::{Visitor, walk_pat};
|
use rustc_hir::intravisit::{Visitor, walk_pat};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
|
use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind, PatExpr, PatExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef};
|
use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef};
|
||||||
use rustc_span::{Span, sym};
|
use rustc_span::{Span, sym};
|
||||||
@ -126,8 +126,8 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
|
|||||||
// scrutinee derives PartialEq and the pattern is a constant.
|
// scrutinee derives PartialEq and the pattern is a constant.
|
||||||
let pat_ref_count = match pat.kind {
|
let pat_ref_count = match pat.kind {
|
||||||
// string literals are already a reference.
|
// string literals are already a reference.
|
||||||
PatKind::Lit(Expr {
|
PatKind::Lit(PatExpr {
|
||||||
kind: ExprKind::Lit(lit),
|
kind: PatExprKind::Lit { lit, negated: false },
|
||||||
..
|
..
|
||||||
}) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1,
|
}) if lit.node.is_str() || lit.node.is_bytestr() => pat_ref_count + 1,
|
||||||
_ => pat_ref_count,
|
_ => pat_ref_count,
|
||||||
|
@ -11,7 +11,7 @@ use clippy_utils::visitors::{Descend, for_each_expr};
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_ast::{BinOpKind, LitKind};
|
use rustc_ast::{BinOpKind, LitKind};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, PatKind};
|
use rustc_hir::{Expr, ExprKind, PatExprKind, PatKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
@ -171,7 +171,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<
|
|||||||
return ControlFlow::Break(());
|
return ControlFlow::Break(());
|
||||||
}
|
}
|
||||||
if arm.pat.walk_short(|pat| match pat.kind {
|
if arm.pat.walk_short(|pat| match pat.kind {
|
||||||
PatKind::Lit(expr) if let ExprKind::Lit(lit) = expr.kind => {
|
PatKind::Lit(expr) if let PatExprKind::Lit { lit, negated: false } = expr.kind => {
|
||||||
if let LitKind::Char(_) = lit.node {
|
if let LitKind::Char(_) = lit.node {
|
||||||
set_char_spans.push(lit.span);
|
set_char_spans.push(lit.span);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
|
|||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind,
|
self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind,
|
||||||
FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, StructTailExpr, TyKind,
|
FnRetTy, HirId, Lit, PatExprKind, PatKind, QPath, StmtKind, StructTailExpr, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
@ -643,6 +643,27 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||||||
self.expr(expr);
|
self.expr(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pat_expr(&self, lit: &Binding<&hir::PatExpr<'_>>) {
|
||||||
|
let kind = |kind| chain!(self, "let PatExprKind::{kind} = {lit}.kind");
|
||||||
|
macro_rules! kind {
|
||||||
|
($($t:tt)*) => (kind(format_args!($($t)*)));
|
||||||
|
}
|
||||||
|
match lit.value.kind {
|
||||||
|
PatExprKind::Lit { lit, negated } => {
|
||||||
|
bind!(self, lit);
|
||||||
|
bind!(self, negated);
|
||||||
|
kind!("Lit{{ref {lit}, {negated} }}");
|
||||||
|
self.lit(lit);
|
||||||
|
},
|
||||||
|
PatExprKind::ConstBlock(_) => kind!("ConstBlock(_)"),
|
||||||
|
PatExprKind::Path(ref qpath) => {
|
||||||
|
bind!(self, qpath);
|
||||||
|
kind!("Path(ref {qpath})");
|
||||||
|
self.qpath(qpath);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn pat(&self, pat: &Binding<&hir::Pat<'_>>) {
|
fn pat(&self, pat: &Binding<&hir::Pat<'_>>) {
|
||||||
let kind = |kind| chain!(self, "let PatKind::{kind} = {pat}.kind");
|
let kind = |kind| chain!(self, "let PatKind::{kind} = {pat}.kind");
|
||||||
macro_rules! kind {
|
macro_rules! kind {
|
||||||
@ -721,13 +742,13 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||||||
PatKind::Lit(lit_expr) => {
|
PatKind::Lit(lit_expr) => {
|
||||||
bind!(self, lit_expr);
|
bind!(self, lit_expr);
|
||||||
kind!("Lit({lit_expr})");
|
kind!("Lit({lit_expr})");
|
||||||
self.expr(lit_expr);
|
self.pat_expr(lit_expr);
|
||||||
},
|
},
|
||||||
PatKind::Range(start, end, end_kind) => {
|
PatKind::Range(start, end, end_kind) => {
|
||||||
opt_bind!(self, start, end);
|
opt_bind!(self, start, end);
|
||||||
kind!("Range({start}, {end}, RangeEnd::{end_kind:?})");
|
kind!("Range({start}, {end}, RangeEnd::{end_kind:?})");
|
||||||
start.if_some(|e| self.expr(e));
|
start.if_some(|e| self.pat_expr(e));
|
||||||
end.if_some(|e| self.expr(e));
|
end.if_some(|e| self.pat_expr(e));
|
||||||
},
|
},
|
||||||
PatKind::Slice(start, middle, end) => {
|
PatKind::Slice(start, middle, end) => {
|
||||||
bind!(self, start, end);
|
bind!(self, start, end);
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
//! executable MIR bodies, so we have to do this instead.
|
//! executable MIR bodies, so we have to do this instead.
|
||||||
#![allow(clippy::float_cmp)]
|
#![allow(clippy::float_cmp)]
|
||||||
|
|
||||||
use crate::macros::HirNode;
|
|
||||||
use crate::source::{SpanRangeExt, walk_span_to_context};
|
use crate::source::{SpanRangeExt, walk_span_to_context};
|
||||||
use crate::{clip, is_direct_expn_of, sext, unsext};
|
use crate::{clip, is_direct_expn_of, sext, unsext};
|
||||||
|
|
||||||
@ -13,7 +12,7 @@ use rustc_apfloat::ieee::{Half, Quad};
|
|||||||
use rustc_ast::ast::{self, LitFloatType, LitKind};
|
use rustc_ast::ast::{self, LitFloatType, LitKind};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
|
use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp, PatExpr, PatExprKind};
|
||||||
use rustc_lexer::tokenize;
|
use rustc_lexer::tokenize;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::ConstValue;
|
use rustc_middle::mir::ConstValue;
|
||||||
@ -442,30 +441,48 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eval_pat_expr(&self, pat_expr: &PatExpr<'_>) -> Option<Constant<'tcx>> {
|
||||||
|
match &pat_expr.kind {
|
||||||
|
PatExprKind::Lit { lit, negated } => {
|
||||||
|
let ty = self.typeck.node_type_opt(pat_expr.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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn qpath(&self, qpath: &QPath<'_>, hir_id: HirId) -> Option<Constant<'tcx>> {
|
||||||
|
let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, hir_id).opt_def_id() {
|
||||||
|
self.tcx.crate_name(def_id.krate) == sym::core
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
self.fetch_path_and_apply(qpath, hir_id, self.typeck.node_type(hir_id), |self_, result| {
|
||||||
|
let result = mir_to_const(self_.tcx, result)?;
|
||||||
|
// If source is already Constant we wouldn't want to override it with CoreConstant
|
||||||
|
self_.source.set(
|
||||||
|
if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
|
||||||
|
ConstantSource::CoreConstant
|
||||||
|
} else {
|
||||||
|
ConstantSource::Constant
|
||||||
|
},
|
||||||
|
);
|
||||||
|
Some(result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Simple constant folding: Insert an expression, get a constant or none.
|
/// Simple constant folding: Insert an expression, get a constant or none.
|
||||||
fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
|
fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
|
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
|
||||||
ExprKind::DropTemps(e) => self.expr(e),
|
ExprKind::DropTemps(e) => self.expr(e),
|
||||||
ExprKind::Path(ref qpath) => {
|
ExprKind::Path(ref qpath) => self.qpath(qpath, e.hir_id),
|
||||||
let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, e.hir_id()).opt_def_id() {
|
|
||||||
self.tcx.crate_name(def_id.krate) == sym::core
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| {
|
|
||||||
let result = mir_to_const(self_.tcx, result)?;
|
|
||||||
// If source is already Constant we wouldn't want to override it with CoreConstant
|
|
||||||
self_.source.set(
|
|
||||||
if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
|
|
||||||
ConstantSource::CoreConstant
|
|
||||||
} else {
|
|
||||||
ConstantSource::Constant
|
|
||||||
},
|
|
||||||
);
|
|
||||||
Some(result)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
ExprKind::Block(block, _) => self.block(block),
|
ExprKind::Block(block, _) => self.block(block),
|
||||||
ExprKind::Lit(lit) => {
|
ExprKind::Lit(lit) => {
|
||||||
if is_direct_expn_of(e.span, "cfg").is_some() {
|
if is_direct_expn_of(e.span, "cfg").is_some() {
|
||||||
|
@ -9,8 +9,8 @@ use rustc_hir::def::{DefKind, Res};
|
|||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField,
|
AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField,
|
||||||
ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName,
|
ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName,
|
||||||
Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty,
|
Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
|
||||||
TyKind,
|
TraitBoundModifiers, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lexer::{TokenKind, tokenize};
|
use rustc_lexer::{TokenKind, tokenize};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -489,6 +489,24 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
li.name == ri.name && self.eq_pat(lp, rp)
|
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) {
|
||||||
|
(
|
||||||
|
&PatExprKind::Lit {
|
||||||
|
lit: left,
|
||||||
|
negated: left_neg,
|
||||||
|
},
|
||||||
|
&PatExprKind::Lit {
|
||||||
|
lit: right,
|
||||||
|
negated: right_neg,
|
||||||
|
},
|
||||||
|
) => left_neg == right_neg && left.node == right.node,
|
||||||
|
(PatExprKind::ConstBlock(left), PatExprKind::ConstBlock(right)) => self.eq_body(left.body, right.body),
|
||||||
|
(PatExprKind::Path(left), PatExprKind::Path(right)) => self.eq_qpath(left, right),
|
||||||
|
(PatExprKind::Lit { .. } | PatExprKind::ConstBlock(..) | PatExprKind::Path(..), _) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether two patterns are the same.
|
/// Checks whether two patterns are the same.
|
||||||
fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
|
fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
|
||||||
match (&left.kind, &right.kind) {
|
match (&left.kind, &right.kind) {
|
||||||
@ -507,11 +525,11 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||||||
eq
|
eq
|
||||||
},
|
},
|
||||||
(PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
|
(PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
|
||||||
(&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r),
|
(&PatKind::Lit(l), &PatKind::Lit(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::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)) => {
|
(&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_expr(a, b))
|
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_expr(a, b))
|
&& both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b))
|
||||||
&& (li == ri)
|
&& (li == ri)
|
||||||
},
|
},
|
||||||
(&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
|
(&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
|
||||||
@ -1073,6 +1091,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
// self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
|
// 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 {
|
||||||
|
PatExprKind::Lit { lit, negated } => {
|
||||||
|
lit.node.hash(&mut self.s);
|
||||||
|
negated.hash(&mut self.s);
|
||||||
|
},
|
||||||
|
PatExprKind::ConstBlock(c) => self.hash_body(c.body),
|
||||||
|
PatExprKind::Path(qpath) => self.hash_qpath(qpath),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
|
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
|
||||||
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
@ -1084,7 +1114,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
|
PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
|
||||||
PatKind::Lit(expr) => self.hash_expr(expr),
|
PatKind::Lit(expr) => self.hash_pat_expr(expr),
|
||||||
PatKind::Or(pats) => {
|
PatKind::Or(pats) => {
|
||||||
for pat in pats {
|
for pat in pats {
|
||||||
self.hash_pat(pat);
|
self.hash_pat(pat);
|
||||||
@ -1093,10 +1123,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
PatKind::Path(ref qpath) => self.hash_qpath(qpath),
|
PatKind::Path(ref qpath) => self.hash_qpath(qpath),
|
||||||
PatKind::Range(s, e, i) => {
|
PatKind::Range(s, e, i) => {
|
||||||
if let Some(s) = s {
|
if let Some(s) = s {
|
||||||
self.hash_expr(s);
|
self.hash_pat_expr(s);
|
||||||
}
|
}
|
||||||
if let Some(e) = e {
|
if let Some(e) = e {
|
||||||
self.hash_expr(e);
|
self.hash_pat_expr(e);
|
||||||
}
|
}
|
||||||
std::mem::discriminant(&i).hash(&mut self.s);
|
std::mem::discriminant(&i).hash(&mut self.s);
|
||||||
},
|
},
|
||||||
|
@ -31,7 +31,7 @@ if let StmtKind::Let(local) = stmt.kind
|
|||||||
if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind
|
if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind
|
||||||
&& let ExprKind::Let(let_expr) = cond.kind
|
&& let ExprKind::Let(let_expr) = cond.kind
|
||||||
&& let PatKind::Lit(lit_expr) = let_expr.pat.kind
|
&& let PatKind::Lit(lit_expr) = let_expr.pat.kind
|
||||||
&& let ExprKind::Lit(ref lit) = lit_expr.kind
|
&& let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
|
||||||
&& let LitKind::Bool(true) = lit.node
|
&& let LitKind::Bool(true) = lit.node
|
||||||
&& let ExprKind::Path(ref qpath) = let_expr.init.kind
|
&& let ExprKind::Path(ref qpath) = let_expr.init.kind
|
||||||
&& match_qpath(qpath, &["a"])
|
&& match_qpath(qpath, &["a"])
|
||||||
|
@ -77,7 +77,7 @@ if let Some(higher::While { condition: condition, body: body }) = higher::While:
|
|||||||
}
|
}
|
||||||
if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr)
|
if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr)
|
||||||
&& let PatKind::Lit(lit_expr) = let_pat.kind
|
&& let PatKind::Lit(lit_expr) = let_pat.kind
|
||||||
&& let ExprKind::Lit(ref lit) = lit_expr.kind
|
&& let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
|
||||||
&& let LitKind::Bool(true) = lit.node
|
&& let LitKind::Bool(true) = lit.node
|
||||||
&& let ExprKind::Path(ref qpath) = let_expr.kind
|
&& let ExprKind::Path(ref qpath) = let_expr.kind
|
||||||
&& match_qpath(qpath, &["a"])
|
&& match_qpath(qpath, &["a"])
|
||||||
|
@ -5,13 +5,13 @@ if let StmtKind::Let(local) = stmt.kind
|
|||||||
&& let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node
|
&& let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node
|
||||||
&& arms.len() == 3
|
&& arms.len() == 3
|
||||||
&& let PatKind::Lit(lit_expr) = arms[0].pat.kind
|
&& let PatKind::Lit(lit_expr) = arms[0].pat.kind
|
||||||
&& let ExprKind::Lit(ref lit1) = lit_expr.kind
|
&& let PatExprKind::Lit{ref lit1, negated } = lit_expr.kind
|
||||||
&& let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node
|
&& let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node
|
||||||
&& arms[0].guard.is_none()
|
&& arms[0].guard.is_none()
|
||||||
&& let ExprKind::Lit(ref lit2) = arms[0].body.kind
|
&& let ExprKind::Lit(ref lit2) = arms[0].body.kind
|
||||||
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node
|
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node
|
||||||
&& let PatKind::Lit(lit_expr1) = arms[1].pat.kind
|
&& let PatKind::Lit(lit_expr1) = arms[1].pat.kind
|
||||||
&& let ExprKind::Lit(ref lit3) = lit_expr1.kind
|
&& let PatExprKind::Lit{ref lit3, negated1 } = lit_expr1.kind
|
||||||
&& let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node
|
&& let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node
|
||||||
&& arms[1].guard.is_none()
|
&& arms[1].guard.is_none()
|
||||||
&& let ExprKind::Block(block, None) = arms[1].body.kind
|
&& let ExprKind::Block(block, None) = arms[1].body.kind
|
||||||
|
@ -24,7 +24,7 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind
|
|||||||
&& fields.len() == 1
|
&& fields.len() == 1
|
||||||
&& fields[0].ident.as_str() == "field"
|
&& fields[0].ident.as_str() == "field"
|
||||||
&& let PatKind::Lit(lit_expr) = fields[0].pat.kind
|
&& let PatKind::Lit(lit_expr) = fields[0].pat.kind
|
||||||
&& let ExprKind::Lit(ref lit) = lit_expr.kind
|
&& let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
|
||||||
&& let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
|
&& let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
|
||||||
&& arm.guard.is_none()
|
&& arm.guard.is_none()
|
||||||
&& let ExprKind::Block(block, None) = arm.body.kind
|
&& let ExprKind::Block(block, None) = arm.body.kind
|
||||||
@ -37,7 +37,7 @@ if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind
|
|||||||
&& match_qpath(qpath, &["TestTuple"])
|
&& match_qpath(qpath, &["TestTuple"])
|
||||||
&& fields.len() == 1
|
&& fields.len() == 1
|
||||||
&& let PatKind::Lit(lit_expr) = fields[0].kind
|
&& let PatKind::Lit(lit_expr) = fields[0].kind
|
||||||
&& let ExprKind::Lit(ref lit) = lit_expr.kind
|
&& let PatExprKind::Lit{ref lit, negated } = lit_expr.kind
|
||||||
&& let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
|
&& let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
|
||||||
&& arm.guard.is_none()
|
&& arm.guard.is_none()
|
||||||
&& let ExprKind::Block(block, None) = arm.body.kind
|
&& let ExprKind::Block(block, None) = arm.body.kind
|
||||||
|
@ -14,4 +14,4 @@ extern crate std;
|
|||||||
|
|
||||||
fn main() ({ } as ())
|
fn main() ({ } as ())
|
||||||
|
|
||||||
fn foo((-(128 as i8) as i8)...(127 as i8): i8) ({ } as ())
|
fn foo(-128...127: i8) ({ } as ())
|
||||||
|
Loading…
Reference in New Issue
Block a user