mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #3675 - mikerite:fix-build-20190120, r=matthiaskrgr
Fix build 20190120
This commit is contained in:
commit
5b64f6875e
@ -376,8 +376,9 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
|
||||
fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, block: &Block) -> bool {
|
||||
if let Some(stmt) = block.stmts.first() {
|
||||
match &stmt.node {
|
||||
StmtKind::Decl(_, _) => true,
|
||||
StmtKind::Expr(expr, _) | StmtKind::Semi(expr, _) => is_relevant_expr(tcx, tables, expr),
|
||||
StmtKind::Local(_) => true,
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(tcx, tables, expr),
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
block.expr.as_ref().map_or(false, |e| is_relevant_expr(tcx, tables, e))
|
||||
|
@ -14,6 +14,7 @@ use std::convert::TryInto;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use syntax::ast::{FloatTy, LitKind};
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::symbol::Symbol;
|
||||
|
||||
/// A `LitKind`-like enum to fold constant `Expr`s into.
|
||||
#[derive(Debug, Clone)]
|
||||
@ -38,6 +39,8 @@ pub enum Constant {
|
||||
Repeat(Box<Constant>, u64),
|
||||
/// a tuple of constants
|
||||
Tuple(Vec<Constant>),
|
||||
/// a literal with syntax error
|
||||
Err(Symbol),
|
||||
}
|
||||
|
||||
impl PartialEq for Constant {
|
||||
@ -103,6 +106,9 @@ impl Hash for Constant {
|
||||
c.hash(state);
|
||||
l.hash(state);
|
||||
},
|
||||
Constant::Err(ref s) => {
|
||||
s.hash(state);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,6 +161,7 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant {
|
||||
_ => bug!(),
|
||||
},
|
||||
LitKind::Bool(b) => Constant::Bool(b),
|
||||
LitKind::Err(s) => Constant::Err(s),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,18 +120,16 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||
if let Categorization::Rvalue(..) = cmt.cat {
|
||||
let id = map.hir_to_node_id(cmt.hir_id);
|
||||
if let Some(Node::Stmt(st)) = map.find(map.get_parent_node(id)) {
|
||||
if let StmtKind::Decl(ref decl, _) = st.node {
|
||||
if let DeclKind::Local(ref loc) = decl.node {
|
||||
if let Some(ref ex) = loc.init {
|
||||
if let ExprKind::Box(..) = ex.node {
|
||||
if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
|
||||
// let x = box (...)
|
||||
self.set.insert(consume_pat.id);
|
||||
}
|
||||
// TODO Box::new
|
||||
// TODO vec![]
|
||||
// TODO "foo".to_owned() and friends
|
||||
if let StmtKind::Local(ref loc) = st.node {
|
||||
if let Some(ref ex) = loc.init {
|
||||
if let ExprKind::Box(..) = ex.node {
|
||||
if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
|
||||
// let x = box (...)
|
||||
self.set.insert(consume_pat.id);
|
||||
}
|
||||
// TODO Box::new
|
||||
// TODO vec![]
|
||||
// TODO "foo".to_owned() and friends
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,14 +89,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
|
||||
}
|
||||
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||
match stmt.node {
|
||||
StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => DivergenceVisitor { cx }.maybe_walk_expr(e),
|
||||
StmtKind::Decl(ref d, _) => {
|
||||
if let DeclKind::Local(ref local) = d.node {
|
||||
if let Local { init: Some(ref e), .. } = **local {
|
||||
DivergenceVisitor { cx }.visit_expr(e);
|
||||
}
|
||||
StmtKind::Local(ref local) => {
|
||||
if let Local { init: Some(ref e), .. } = **local {
|
||||
DivergenceVisitor { cx }.visit_expr(e);
|
||||
}
|
||||
},
|
||||
StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => DivergenceVisitor { cx }.maybe_walk_expr(e),
|
||||
StmtKind::Item(..) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -269,18 +268,14 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> St
|
||||
|
||||
fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly {
|
||||
match stmt.node {
|
||||
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => check_expr(vis, expr),
|
||||
StmtKind::Decl(ref decl, _) => {
|
||||
// If the declaration is of a local variable, check its initializer
|
||||
// expression if it has one. Otherwise, keep going.
|
||||
let local = match decl.node {
|
||||
DeclKind::Local(ref local) => Some(local),
|
||||
_ => None,
|
||||
};
|
||||
local
|
||||
.and_then(|local| local.init.as_ref())
|
||||
.map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr))
|
||||
},
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => check_expr(vis, expr),
|
||||
// If the declaration is of a local variable, check its initializer
|
||||
// expression if it has one. Otherwise, keep going.
|
||||
StmtKind::Local(ref local) => local
|
||||
.init
|
||||
.as_ref()
|
||||
.map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)),
|
||||
_ => StopEarly::KeepGoing,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,10 +68,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
|
||||
while let Some(stmt) = it.next() {
|
||||
if_chain! {
|
||||
if let Some(expr) = it.peek();
|
||||
if let hir::StmtKind::Decl(ref decl, _) = stmt.node;
|
||||
if let hir::DeclKind::Local(ref decl) = decl.node;
|
||||
if let hir::PatKind::Binding(mode, canonical_id, ident, None) = decl.pat.node;
|
||||
if let hir::StmtKind::Expr(ref if_, _) = expr.node;
|
||||
if let hir::StmtKind::Local(ref local) = stmt.node;
|
||||
if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.node;
|
||||
if let hir::StmtKind::Expr(ref if_) = expr.node;
|
||||
if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node;
|
||||
if !used_in_expr(cx, canonical_id, cond);
|
||||
if let hir::ExprKind::Block(ref then, _) = then.node;
|
||||
@ -84,7 +83,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
|
||||
if let hir::ExprKind::Block(ref else_, _) = else_.node {
|
||||
if let Some(default) = check_assign(cx, canonical_id, else_) {
|
||||
(else_.stmts.len() > 1, default)
|
||||
} else if let Some(ref default) = decl.init {
|
||||
} else if let Some(ref default) = local.init {
|
||||
(true, &**default)
|
||||
} else {
|
||||
continue;
|
||||
@ -92,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else if let Some(ref default) = decl.init {
|
||||
} else if let Some(ref default) = local.init {
|
||||
(false, &**default)
|
||||
} else {
|
||||
continue;
|
||||
@ -169,7 +168,7 @@ fn check_assign<'a, 'tcx>(
|
||||
if_chain! {
|
||||
if block.expr.is_none();
|
||||
if let Some(expr) = block.stmts.iter().last();
|
||||
if let hir::StmtKind::Semi(ref expr, _) = expr.node;
|
||||
if let hir::StmtKind::Semi(ref expr) = expr.node;
|
||||
if let hir::ExprKind::Assign(ref var, ref value) = expr.node;
|
||||
if let hir::ExprKind::Path(ref qpath) = var.node;
|
||||
if let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id);
|
||||
|
@ -3,7 +3,7 @@ use if_chain::if_chain;
|
||||
use itertools::Itertools;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id;
|
||||
use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
|
||||
use rustc::hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::middle::region;
|
||||
@ -597,7 +597,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
}
|
||||
|
||||
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||
if let StmtKind::Semi(ref expr, _) = stmt.node {
|
||||
if let StmtKind::Semi(ref expr) = stmt.node {
|
||||
if let ExprKind::MethodCall(ref method, _, ref args) = expr.node {
|
||||
if args.len() == 1 && method.ident.name == "collect" && match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
span_lint(
|
||||
@ -668,13 +668,7 @@ fn never_loop_block(block: &Block, main_loop_id: NodeId) -> NeverLoopResult {
|
||||
fn stmt_to_expr(stmt: &Stmt) -> Option<&Expr> {
|
||||
match stmt.node {
|
||||
StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e),
|
||||
StmtKind::Decl(ref d, ..) => decl_to_expr(d),
|
||||
}
|
||||
}
|
||||
|
||||
fn decl_to_expr(decl: &Decl) -> Option<&Expr> {
|
||||
match decl.node {
|
||||
DeclKind::Local(ref local) => local.init.as_ref().map(|p| &**p),
|
||||
StmtKind::Local(ref local) => local.init.as_ref().map(|p| &**p),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -942,8 +936,8 @@ fn get_indexed_assignments<'a, 'tcx>(
|
||||
stmts
|
||||
.iter()
|
||||
.map(|stmt| match stmt.node {
|
||||
StmtKind::Decl(..) => None,
|
||||
StmtKind::Expr(ref e, _node_id) | StmtKind::Semi(ref e, _node_id) => Some(get_assignment(cx, e, var)),
|
||||
StmtKind::Local(..) | StmtKind::Item(..) => None,
|
||||
StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => Some(get_assignment(cx, e, var)),
|
||||
})
|
||||
.chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var))))
|
||||
.filter_map(|op| op)
|
||||
@ -1976,13 +1970,9 @@ fn extract_expr_from_first_stmt(block: &Block) -> Option<&Expr> {
|
||||
if block.stmts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if let StmtKind::Decl(ref decl, _) = block.stmts[0].node {
|
||||
if let DeclKind::Local(ref local) = decl.node {
|
||||
if let Some(ref expr) = local.init {
|
||||
Some(expr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let StmtKind::Local(ref local) = block.stmts[0].node {
|
||||
if let Some(ref expr) = local.init {
|
||||
Some(expr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1996,8 +1986,8 @@ fn extract_first_expr(block: &Block) -> Option<&Expr> {
|
||||
match block.expr {
|
||||
Some(ref expr) if block.stmts.is_empty() => Some(expr),
|
||||
None if !block.stmts.is_empty() => match block.stmts[0].node {
|
||||
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => Some(expr),
|
||||
StmtKind::Decl(..) => None,
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => Some(expr),
|
||||
StmtKind::Local(..) | StmtKind::Item(..) => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
@ -2095,9 +2085,9 @@ struct InitializeVisitor<'a, 'tcx: 'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
|
||||
fn visit_decl(&mut self, decl: &'tcx Decl) {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx Stmt) {
|
||||
// Look for declarations of the variable
|
||||
if let DeclKind::Local(ref local) = decl.node {
|
||||
if let StmtKind::Local(ref local) = stmt.node {
|
||||
if local.pat.id == self.var_id {
|
||||
if let PatKind::Binding(_, _, ident, _) = local.pat.node {
|
||||
self.name = Some(ident.name);
|
||||
@ -2114,7 +2104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_decl(self, decl);
|
||||
walk_stmt(self, stmt);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||
@ -2261,7 +2251,7 @@ struct LoopNestVisitor {
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx Stmt) {
|
||||
if stmt.node.id() == self.id {
|
||||
if stmt.id == self.id {
|
||||
self.nesting = LookFurther;
|
||||
} else if self.nesting == Unknown {
|
||||
walk_stmt(self, stmt);
|
||||
|
@ -131,9 +131,10 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr) ->
|
||||
// If block only contains statements,
|
||||
// reduce `{ X; }` to `X` or `X;`
|
||||
match inner_stmt.node {
|
||||
hir::StmtKind::Decl(ref d, _) => Some(d.span),
|
||||
hir::StmtKind::Expr(ref e, _) => Some(e.span),
|
||||
hir::StmtKind::Semi(_, _) => Some(inner_stmt.span),
|
||||
hir::StmtKind::Local(ref local) => Some(local.span),
|
||||
hir::StmtKind::Expr(ref e) => Some(e.span),
|
||||
hir::StmtKind::Semi(..) => Some(inner_stmt.span),
|
||||
hir::StmtKind::Item(..) => None,
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
@ -250,7 +251,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
return;
|
||||
}
|
||||
|
||||
if let hir::StmtKind::Semi(ref expr, _) = stmt.node {
|
||||
if let hir::StmtKind::Semi(ref expr) = stmt.node {
|
||||
if let Some(arglists) = method_chain_args(expr, &["map"]) {
|
||||
lint_map_unit_fn(cx, stmt, expr, arglists[0]);
|
||||
}
|
||||
|
@ -1336,12 +1336,10 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
|
||||
_ => {},
|
||||
},
|
||||
hir::Node::Stmt(stmt) => {
|
||||
if let hir::StmtKind::Decl(ref decl, _) = stmt.node {
|
||||
if let hir::DeclKind::Local(ref loc) = decl.node {
|
||||
if let hir::PatKind::Ref(..) = loc.pat.node {
|
||||
// let ref y = *x borrows x, let ref y = x.clone() does not
|
||||
return;
|
||||
}
|
||||
if let hir::StmtKind::Local(ref loc) = stmt.node {
|
||||
if let hir::PatKind::Ref(..) = loc.pat.node {
|
||||
// let ref y = *x borrows x, let ref y = x.clone() does not
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -277,8 +277,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
|
||||
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) {
|
||||
if_chain! {
|
||||
if let StmtKind::Decl(ref d, _) = s.node;
|
||||
if let DeclKind::Local(ref l) = d.node;
|
||||
if let StmtKind::Local(ref l) = s.node;
|
||||
if let PatKind::Binding(an, _, i, None) = l.pat.node;
|
||||
if let Some(ref init) = l.init;
|
||||
then {
|
||||
@ -316,7 +315,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
}
|
||||
};
|
||||
if_chain! {
|
||||
if let StmtKind::Semi(ref expr, _) = s.node;
|
||||
if let StmtKind::Semi(ref expr) = s.node;
|
||||
if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node;
|
||||
if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
|
||||
if let Some(sugg) = Sugg::hir_opt(cx, a);
|
||||
|
@ -267,7 +267,7 @@ fn fetch_bool_block(block: &Block) -> Expression {
|
||||
match (&*block.stmts, block.expr.as_ref()) {
|
||||
(&[], Some(e)) => fetch_bool_expr(&**e),
|
||||
(&[ref e], None) => {
|
||||
if let StmtKind::Semi(ref e, _) = e.node {
|
||||
if let StmtKind::Semi(ref e) = e.node {
|
||||
if let ExprKind::Ret(_) = e.node {
|
||||
fetch_bool_expr(&**e)
|
||||
} else {
|
||||
|
@ -368,8 +368,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
|
||||
Node::Stmt(s) => {
|
||||
// `let <pat> = x;`
|
||||
if_chain! {
|
||||
if let StmtKind::Decl(ref decl, _) = s.node;
|
||||
if let DeclKind::Local(ref local) = decl.node;
|
||||
if let StmtKind::Local(ref local) = s.node;
|
||||
then {
|
||||
self.spans_need_deref
|
||||
.entry(vid)
|
||||
|
@ -104,7 +104,7 @@ impl LintPass for Pass {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||
if let StmtKind::Semi(ref expr, _) = stmt.node {
|
||||
if let StmtKind::Semi(ref expr) = stmt.node {
|
||||
if has_no_effect(cx, expr) {
|
||||
span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
|
||||
} else if let Some(reduced) = reduce_expression(cx, expr) {
|
||||
|
@ -139,7 +139,7 @@ impl Pass {
|
||||
if_chain! {
|
||||
if block.stmts.len() == 1;
|
||||
if let Some(expr) = block.stmts.iter().last();
|
||||
if let StmtKind::Semi(ref expr, _) = expr.node;
|
||||
if let StmtKind::Semi(ref expr) = expr.node;
|
||||
if let ExprKind::Ret(ref ret_expr) = expr.node;
|
||||
if let &Some(ref ret_expr) = ret_expr;
|
||||
|
||||
|
@ -115,8 +115,9 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding
|
||||
let len = bindings.len();
|
||||
for stmt in &block.stmts {
|
||||
match stmt.node {
|
||||
StmtKind::Decl(ref decl, _) => check_decl(cx, decl, bindings),
|
||||
StmtKind::Expr(ref e, _) | StmtKind::Semi(ref e, _) => check_expr(cx, e, bindings),
|
||||
StmtKind::Local(ref local) => check_local(cx, local, bindings),
|
||||
StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
|
||||
StmtKind::Item(..) => {},
|
||||
}
|
||||
}
|
||||
if let Some(ref o) = block.expr {
|
||||
@ -125,30 +126,28 @@ fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, binding
|
||||
bindings.truncate(len);
|
||||
}
|
||||
|
||||
fn check_decl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: &mut Vec<(Name, Span)>) {
|
||||
if in_external_macro(cx.sess(), decl.span) {
|
||||
fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local, bindings: &mut Vec<(Name, Span)>) {
|
||||
if in_external_macro(cx.sess(), local.span) {
|
||||
return;
|
||||
}
|
||||
if higher::is_from_for_desugar(decl) {
|
||||
if higher::is_from_for_desugar(local) {
|
||||
return;
|
||||
}
|
||||
if let DeclKind::Local(ref local) = decl.node {
|
||||
let Local {
|
||||
ref pat,
|
||||
ref ty,
|
||||
ref init,
|
||||
span,
|
||||
..
|
||||
} = **local;
|
||||
if let Some(ref t) = *ty {
|
||||
check_ty(cx, t, bindings)
|
||||
}
|
||||
if let Some(ref o) = *init {
|
||||
check_expr(cx, o, bindings);
|
||||
check_pat(cx, pat, Some(o), span, bindings);
|
||||
} else {
|
||||
check_pat(cx, pat, None, span, bindings);
|
||||
}
|
||||
let Local {
|
||||
ref pat,
|
||||
ref ty,
|
||||
ref init,
|
||||
span,
|
||||
..
|
||||
} = *local;
|
||||
if let Some(ref t) = *ty {
|
||||
check_ty(cx, t, bindings)
|
||||
}
|
||||
if let Some(ref o) = *init {
|
||||
check_expr(cx, o, bindings);
|
||||
check_pat(cx, pat, Some(o), span, bindings);
|
||||
} else {
|
||||
check_pat(cx, pat, None, span, bindings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,8 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||
// Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
|
||||
if_chain! {
|
||||
if let StmtKind::Decl(ref decl, _) = stmt.node;
|
||||
if let DeclKind::Local(ref local) = decl.node;
|
||||
if let StmtKind::Local(ref local) = stmt.node;
|
||||
if let PatKind::Binding(BindingAnnotation::Mutable, _, variable_name, None) = local.pat.node;
|
||||
if let Some(ref init) = local.init;
|
||||
if let Some(ref len_arg) = Self::is_vec_with_capacity(init);
|
||||
@ -104,7 +103,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
len_expr: len_arg,
|
||||
};
|
||||
|
||||
Self::search_initialization(cx, vi, stmt.node.id());
|
||||
Self::search_initialization(cx, vi, stmt.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,7 +286,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx Stmt) {
|
||||
if self.initialization_found {
|
||||
match stmt.node {
|
||||
StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => {
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
|
||||
self.search_slow_extend_filling(expr);
|
||||
self.search_slow_resize_filling(expr);
|
||||
},
|
||||
|
@ -71,17 +71,16 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) {
|
||||
for w in block.stmts.windows(3) {
|
||||
if_chain! {
|
||||
// let t = foo();
|
||||
if let StmtKind::Decl(ref tmp, _) = w[0].node;
|
||||
if let DeclKind::Local(ref tmp) = tmp.node;
|
||||
if let StmtKind::Local(ref tmp) = w[0].node;
|
||||
if let Some(ref tmp_init) = tmp.init;
|
||||
if let PatKind::Binding(_, _, ident, None) = tmp.pat.node;
|
||||
|
||||
// foo() = bar();
|
||||
if let StmtKind::Semi(ref first, _) = w[1].node;
|
||||
if let StmtKind::Semi(ref first) = w[1].node;
|
||||
if let ExprKind::Assign(ref lhs1, ref rhs1) = first.node;
|
||||
|
||||
// bar() = t;
|
||||
if let StmtKind::Semi(ref second, _) = w[2].node;
|
||||
if let StmtKind::Semi(ref second) = w[2].node;
|
||||
if let ExprKind::Assign(ref lhs2, ref rhs2) = second.node;
|
||||
if let ExprKind::Path(QPath::Resolved(None, ref rhs2)) = rhs2.node;
|
||||
if rhs2.segments.len() == 1;
|
||||
@ -160,8 +159,8 @@ fn check_manual_swap(cx: &LateContext<'_, '_>, block: &Block) {
|
||||
fn check_suspicious_swap(cx: &LateContext<'_, '_>, block: &Block) {
|
||||
for w in block.stmts.windows(2) {
|
||||
if_chain! {
|
||||
if let StmtKind::Semi(ref first, _) = w[0].node;
|
||||
if let StmtKind::Semi(ref second, _) = w[1].node;
|
||||
if let StmtKind::Semi(ref first) = w[0].node;
|
||||
if let StmtKind::Semi(ref second) = w[1].node;
|
||||
if !differing_macro_contexts(first.span, second.span);
|
||||
if let ExprKind::Assign(ref lhs0, ref rhs0) = first.node;
|
||||
if let ExprKind::Assign(ref lhs1, ref rhs1) = second.node;
|
||||
|
@ -463,28 +463,6 @@ declare_clippy_lint! {
|
||||
"creating a let binding to a value of unit type, which usually can't be used afterwards"
|
||||
}
|
||||
|
||||
fn check_let_unit(cx: &LateContext<'_, '_>, decl: &Decl) {
|
||||
if let DeclKind::Local(ref local) = decl.node {
|
||||
if is_unit(cx.tables.pat_ty(&local.pat)) {
|
||||
if in_external_macro(cx.sess(), decl.span) || in_macro(local.pat.span) {
|
||||
return;
|
||||
}
|
||||
if higher::is_from_for_desugar(decl) {
|
||||
return;
|
||||
}
|
||||
span_lint(
|
||||
cx,
|
||||
LET_UNIT_VALUE,
|
||||
decl.span,
|
||||
&format!(
|
||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
||||
snippet(cx, local.pat.span, "..")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LintPass for LetPass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(LET_UNIT_VALUE)
|
||||
@ -492,8 +470,26 @@ impl LintPass for LetPass {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetPass {
|
||||
fn check_decl(&mut self, cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl) {
|
||||
check_let_unit(cx, decl)
|
||||
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||
if let StmtKind::Local(ref local) = stmt.node {
|
||||
if is_unit(cx.tables.pat_ty(&local.pat)) {
|
||||
if in_external_macro(cx.sess(), stmt.span) || in_macro(local.pat.span) {
|
||||
return;
|
||||
}
|
||||
if higher::is_from_for_desugar(local) {
|
||||
return;
|
||||
}
|
||||
span_lint(
|
||||
cx,
|
||||
LET_UNIT_VALUE,
|
||||
stmt.span,
|
||||
&format!(
|
||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
||||
snippet(cx, local.pat.span, "..")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl LintPass for UnusedIoAmount {
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
|
||||
fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
|
||||
let expr = match s.node {
|
||||
hir::StmtKind::Semi(ref expr, _) | hir::StmtKind::Expr(ref expr, _) => &**expr,
|
||||
hir::StmtKind::Semi(ref expr) | hir::StmtKind::Expr(ref expr) => &**expr,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
use crate::utils::get_attr;
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
|
||||
use rustc::hir::{BindingAnnotation, DeclKind, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind};
|
||||
use rustc::hir::{BindingAnnotation, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind};
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@ -260,6 +260,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
||||
match lit.node {
|
||||
LitKind::Bool(val) => println!(" if let LitKind::Bool({:?}) = {}.node;", val, lit_pat),
|
||||
LitKind::Char(c) => println!(" if let LitKind::Char({:?}) = {}.node;", c, lit_pat),
|
||||
LitKind::Err(val) => println!(" if let LitKind::Err({}) = {}.node;", val, lit_pat),
|
||||
LitKind::Byte(b) => println!(" if let LitKind::Byte({}) = {}.node;", b, lit_pat),
|
||||
// FIXME: also check int type
|
||||
LitKind::Int(i, _) => println!(" if let LitKind::Int({}, _) = {}.node;", i, lit_pat),
|
||||
@ -625,35 +626,26 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
||||
print!(" if let StmtKind::");
|
||||
let current = format!("{}.node", self.current);
|
||||
match s.node {
|
||||
// Could be an item or a local (let) binding:
|
||||
StmtKind::Decl(ref decl, _) => {
|
||||
let decl_pat = self.next("decl");
|
||||
println!("Decl(ref {}, _) = {}", decl_pat, current);
|
||||
print!(" if let DeclKind::");
|
||||
let current = format!("{}.node", decl_pat);
|
||||
match decl.node {
|
||||
// A local (let) binding:
|
||||
DeclKind::Local(ref local) => {
|
||||
let local_pat = self.next("local");
|
||||
println!("Local(ref {}) = {};", local_pat, current);
|
||||
if let Some(ref init) = local.init {
|
||||
let init_pat = self.next("init");
|
||||
println!(" if let Some(ref {}) = {}.init", init_pat, local_pat);
|
||||
self.current = init_pat;
|
||||
self.visit_expr(init);
|
||||
}
|
||||
self.current = format!("{}.pat", local_pat);
|
||||
self.visit_pat(&local.pat);
|
||||
},
|
||||
// An item binding:
|
||||
DeclKind::Item(_) => {
|
||||
println!("Item(item_id) = {};", current);
|
||||
},
|
||||
// A local (let) binding:
|
||||
StmtKind::Local(ref local) => {
|
||||
let local_pat = self.next("local");
|
||||
println!("Local(ref {}) = {};", local_pat, current);
|
||||
if let Some(ref init) = local.init {
|
||||
let init_pat = self.next("init");
|
||||
println!(" if let Some(ref {}) = {}.init", init_pat, local_pat);
|
||||
self.current = init_pat;
|
||||
self.visit_expr(init);
|
||||
}
|
||||
self.current = format!("{}.pat", local_pat);
|
||||
self.visit_pat(&local.pat);
|
||||
},
|
||||
// An item binding:
|
||||
StmtKind::Item(_) => {
|
||||
println!("Item(item_id) = {};", current);
|
||||
},
|
||||
|
||||
// Expr without trailing semi-colon (must have unit type):
|
||||
StmtKind::Expr(ref e, _) => {
|
||||
StmtKind::Expr(ref e) => {
|
||||
let e_pat = self.next("e");
|
||||
println!("Expr(ref {}, _) = {}", e_pat, current);
|
||||
self.current = e_pat;
|
||||
@ -661,7 +653,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
||||
},
|
||||
|
||||
// Expr with trailing semi-colon (may have any type):
|
||||
StmtKind::Semi(ref e, _) => {
|
||||
StmtKind::Semi(ref e) => {
|
||||
let e_pat = self.next("e");
|
||||
println!("Semi(ref {}, _) = {}", e_pat, current);
|
||||
self.current = e_pat;
|
||||
|
@ -148,8 +148,8 @@ pub fn range<'a, 'b, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'b hir::Expr) -> O
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a `let` decl is from a `for` loop desugaring.
|
||||
pub fn is_from_for_desugar(decl: &hir::Decl) -> bool {
|
||||
/// Checks if a `let` statement is from a `for` loop desugaring.
|
||||
pub fn is_from_for_desugar(local: &hir::Local) -> bool {
|
||||
// This will detect plain for-loops without an actual variable binding:
|
||||
//
|
||||
// ```
|
||||
@ -158,8 +158,7 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool {
|
||||
// }
|
||||
// ```
|
||||
if_chain! {
|
||||
if let hir::DeclKind::Local(ref loc) = decl.node;
|
||||
if let Some(ref expr) = loc.init;
|
||||
if let Some(ref expr) = local.init;
|
||||
if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.node;
|
||||
then {
|
||||
return true;
|
||||
@ -174,12 +173,8 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool {
|
||||
// // anything
|
||||
// }
|
||||
// ```
|
||||
if_chain! {
|
||||
if let hir::DeclKind::Local(ref loc) = decl.node;
|
||||
if let hir::LocalSource::ForLoopDesugar = loc.source;
|
||||
then {
|
||||
return true;
|
||||
}
|
||||
if let hir::LocalSource::ForLoopDesugar = local.source {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
@ -195,11 +190,10 @@ pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)>
|
||||
if let hir::ExprKind::Loop(ref block, _, _) = arms[0].body.node;
|
||||
if block.expr.is_none();
|
||||
if let [ _, _, ref let_stmt, ref body ] = *block.stmts;
|
||||
if let hir::StmtKind::Decl(ref decl, _) = let_stmt.node;
|
||||
if let hir::DeclKind::Local(ref decl) = decl.node;
|
||||
if let hir::StmtKind::Expr(ref expr, _) = body.node;
|
||||
if let hir::StmtKind::Local(ref local) = let_stmt.node;
|
||||
if let hir::StmtKind::Expr(ref expr) = body.node;
|
||||
then {
|
||||
return Some((&*decl.pat, &iterargs[0], expr));
|
||||
return Some((&*local.pat, &iterargs[0], expr));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -43,17 +43,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
||||
/// Check whether two statements are the same.
|
||||
pub fn eq_stmt(&mut self, left: &Stmt, right: &Stmt) -> bool {
|
||||
match (&left.node, &right.node) {
|
||||
(&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => {
|
||||
if let (&DeclKind::Local(ref l), &DeclKind::Local(ref r)) = (&l.node, &r.node) {
|
||||
self.eq_pat(&l.pat, &r.pat)
|
||||
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
|
||||
&& both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
(&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => {
|
||||
self.eq_pat(&l.pat, &r.pat)
|
||||
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
|
||||
&& both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
|
||||
},
|
||||
(&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => {
|
||||
self.eq_expr(l, r)
|
||||
},
|
||||
(&StmtKind::Expr(ref l, _), &StmtKind::Expr(ref r, _))
|
||||
| (&StmtKind::Semi(ref l, _), &StmtKind::Semi(ref r, _)) => self.eq_expr(l, r),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -643,23 +640,24 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||
|
||||
pub fn hash_stmt(&mut self, b: &Stmt) {
|
||||
match b.node {
|
||||
StmtKind::Decl(ref decl, _) => {
|
||||
let c: fn(_, _) -> _ = StmtKind::Decl;
|
||||
StmtKind::Local(ref local) => {
|
||||
let c: fn(_) -> _ = StmtKind::Local;
|
||||
c.hash(&mut self.s);
|
||||
|
||||
if let DeclKind::Local(ref local) = decl.node {
|
||||
if let Some(ref init) = local.init {
|
||||
self.hash_expr(init);
|
||||
}
|
||||
if let Some(ref init) = local.init {
|
||||
self.hash_expr(init);
|
||||
}
|
||||
},
|
||||
StmtKind::Expr(ref expr, _) => {
|
||||
let c: fn(_, _) -> _ = StmtKind::Expr;
|
||||
StmtKind::Item(..) => {
|
||||
let c: fn(_) -> _ = StmtKind::Item;
|
||||
c.hash(&mut self.s);
|
||||
},
|
||||
StmtKind::Expr(ref expr) => {
|
||||
let c: fn(_) -> _ = StmtKind::Expr;
|
||||
c.hash(&mut self.s);
|
||||
self.hash_expr(expr);
|
||||
},
|
||||
StmtKind::Semi(ref expr, _) => {
|
||||
let c: fn(_, _) -> _ = StmtKind::Semi;
|
||||
StmtKind::Semi(ref expr) => {
|
||||
let c: fn(_) -> _ = StmtKind::Semi;
|
||||
c.hash(&mut self.s);
|
||||
self.hash_expr(expr);
|
||||
},
|
||||
|
@ -122,8 +122,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
return;
|
||||
}
|
||||
match stmt.node {
|
||||
hir::StmtKind::Decl(ref decl, _) => print_decl(cx, decl),
|
||||
hir::StmtKind::Expr(ref e, _) | hir::StmtKind::Semi(ref e, _) => print_expr(cx, e, 0),
|
||||
hir::StmtKind::Local(ref local) => {
|
||||
println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id));
|
||||
println!("pattern:");
|
||||
print_pat(cx, &local.pat, 0);
|
||||
if let Some(ref e) = local.init {
|
||||
println!("init expression:");
|
||||
print_expr(cx, e, 0);
|
||||
}
|
||||
},
|
||||
hir::StmtKind::Item(_) => println!("item decl"),
|
||||
hir::StmtKind::Expr(ref e) | hir::StmtKind::Semi(ref e) => print_expr(cx, e, 0),
|
||||
}
|
||||
}
|
||||
// fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx
|
||||
@ -139,21 +148,6 @@ fn has_attr(attrs: &[Attribute]) -> bool {
|
||||
get_attr(attrs, "dump").count() > 0
|
||||
}
|
||||
|
||||
fn print_decl(cx: &LateContext<'_, '_>, decl: &hir::Decl) {
|
||||
match decl.node {
|
||||
hir::DeclKind::Local(ref local) => {
|
||||
println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id));
|
||||
println!("pattern:");
|
||||
print_pat(cx, &local.pat, 0);
|
||||
if let Some(ref e) = local.init {
|
||||
println!("init expression:");
|
||||
print_expr(cx, e, 0);
|
||||
}
|
||||
},
|
||||
hir::DeclKind::Item(_) => println!("item decl"),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::similar_names)]
|
||||
fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) {
|
||||
let ind = " ".repeat(indent);
|
||||
|
@ -5,7 +5,7 @@ use rustc_errors::Applicability;
|
||||
use std::borrow::Cow;
|
||||
use syntax::ast::*;
|
||||
use syntax::parse::{parser, token};
|
||||
use syntax::tokenstream::{ThinTokenStream, TokenStream};
|
||||
use syntax::tokenstream::TokenStream;
|
||||
|
||||
/// **What it does:** This lint warns when you use `println!("")` to
|
||||
/// print a newline.
|
||||
@ -261,9 +261,9 @@ impl EarlyLintPass for Pass {
|
||||
/// ```rust,ignore
|
||||
/// (Some("string to write: {}"), Some(buf))
|
||||
/// ```
|
||||
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option<String>, Option<Expr>) {
|
||||
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option<String>, Option<Expr>) {
|
||||
use fmt_macros::*;
|
||||
let tts = TokenStream::from(tts.clone());
|
||||
let tts = tts.clone();
|
||||
let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false);
|
||||
let mut expr: Option<Expr> = None;
|
||||
if is_write {
|
||||
|
@ -1,6 +1,5 @@
|
||||
if_chain! {
|
||||
if let StmtKind::Decl(ref decl, _) = stmt.node
|
||||
if let DeclKind::Local(ref local) = decl.node;
|
||||
if let StmtKind::Local(ref local) = stmt.node;
|
||||
if let Some(ref init) = local.init
|
||||
if let ExprKind::Cast(ref expr, ref cast_ty) = init.node;
|
||||
if let TyKind::Path(ref qp) = cast_ty.node;
|
||||
|
@ -1,6 +1,5 @@
|
||||
if_chain! {
|
||||
if let StmtKind::Decl(ref decl, _) = stmt.node
|
||||
if let DeclKind::Local(ref local) = decl.node;
|
||||
if let StmtKind::Local(ref local) = stmt.node;
|
||||
if let Some(ref init) = local.init
|
||||
if let ExprKind::Call(ref func, ref args) = init.node;
|
||||
if let ExprKind::Path(ref path) = func.node;
|
||||
|
@ -1,7 +1,6 @@
|
||||
if_chain! {
|
||||
if let ExprKind::Block(ref block) = expr.node;
|
||||
if let StmtKind::Decl(ref decl, _) = block.node
|
||||
if let DeclKind::Local(ref local) = decl.node;
|
||||
if let StmtKind::Local(ref local) = block.node;
|
||||
if let Some(ref init) = local.init
|
||||
if let ExprKind::Match(ref expr, ref arms, MatchSource::ForLoopDesugar) = init.node;
|
||||
if let ExprKind::Call(ref func, ref args) = expr.node;
|
||||
@ -14,8 +13,7 @@ if_chain! {
|
||||
// unimplemented: field checks
|
||||
if arms.len() == 1;
|
||||
if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node;
|
||||
if let StmtKind::Decl(ref decl1, _) = body.node
|
||||
if let DeclKind::Local(ref local1) = decl1.node;
|
||||
if let StmtKind::Local(ref local1) = body.node;
|
||||
if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local1.pat.node;
|
||||
if name.node.as_str() == "__next";
|
||||
if let StmtKind::Expr(ref e, _) = local1.pat.node
|
||||
@ -42,8 +40,7 @@ if_chain! {
|
||||
if arms1[1].pats.len() == 1;
|
||||
if let PatKind::Path(ref path7) = arms1[1].pats[0].node;
|
||||
if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]);
|
||||
if let StmtKind::Decl(ref decl2, _) = path7.node
|
||||
if let DeclKind::Local(ref local2) = decl2.node;
|
||||
if let StmtKind::Local(ref local2) = path7.node;
|
||||
if let Some(ref init1) = local2.init
|
||||
if let ExprKind::Path(ref path8) = init1.node;
|
||||
if match_qpath(path8, &["__next"]);
|
||||
@ -51,8 +48,7 @@ if_chain! {
|
||||
if name1.node.as_str() == "y";
|
||||
if let StmtKind::Expr(ref e1, _) = local2.pat.node
|
||||
if let ExprKind::Block(ref block1) = e1.node;
|
||||
if let StmtKind::Decl(ref decl3, _) = block1.node
|
||||
if let DeclKind::Local(ref local3) = decl3.node;
|
||||
if let StmtKind::Local(ref local3) = block1.node;
|
||||
if let Some(ref init2) = local3.init
|
||||
if let ExprKind::Path(ref path9) = init2.node;
|
||||
if match_qpath(path9, &["y"]);
|
||||
|
Loading…
Reference in New Issue
Block a user