mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 21:53:23 +00:00
Auto merge of #9007 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: none
This commit is contained in:
commit
d7b5cbf065
66 changed files with 208 additions and 192 deletions
|
@ -90,7 +90,7 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
|
|||
diag.span_suggestion(
|
||||
span,
|
||||
"use an inclusive range",
|
||||
sugg.to_owned(),
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for AsUnderscore {
|
|||
diag.span_suggestion(
|
||||
ty.span,
|
||||
"consider giving the type explicitly",
|
||||
format!("{}", ty_resolved),
|
||||
ty_resolved,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -340,7 +340,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
|||
for lint in lint_list {
|
||||
match item.kind {
|
||||
ItemKind::Use(..) => {
|
||||
if is_word(lint, sym!(unused_imports))
|
||||
if is_word(lint, sym::unused_imports)
|
||||
|| is_word(lint, sym::deprecated)
|
||||
|| is_word(lint, sym!(unreachable_pub))
|
||||
|| is_word(lint, sym!(unused))
|
||||
|
@ -355,7 +355,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
|
|||
}
|
||||
},
|
||||
ItemKind::ExternCrate(..) => {
|
||||
if is_word(lint, sym!(unused_imports)) && skip_unused_imports {
|
||||
if is_word(lint, sym::unused_imports) && skip_unused_imports {
|
||||
return;
|
||||
}
|
||||
if is_word(lint, sym!(unused_extern_crates)) {
|
||||
|
|
|
@ -51,7 +51,7 @@ struct ExVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
|
||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||
if let ExprKind::Closure(_, _, eid, _, _) = expr.kind {
|
||||
if let ExprKind::Closure { body, .. } = expr.kind {
|
||||
// do not lint if the closure is called using an iterator (see #1141)
|
||||
if_chain! {
|
||||
if let Some(parent) = get_parent_expr(self.cx, expr);
|
||||
|
@ -64,7 +64,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let body = self.cx.tcx.hir().body(eid);
|
||||
let body = self.cx.tcx.hir().body(body);
|
||||
let ex = &body.value;
|
||||
if let ExprKind::Block(block, _) = ex.kind {
|
||||
if !body.value.span.from_expansion() && !block.stmts.is_empty() {
|
||||
|
|
|
@ -51,8 +51,8 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
|
|||
if count.ident.name == sym::count;
|
||||
if let ExprKind::MethodCall(filter, [filter_recv, filter_arg], _) = count_recv.kind;
|
||||
if filter.ident.name == sym!(filter);
|
||||
if let ExprKind::Closure(_, _, body_id, _, _) = filter_arg.kind;
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
if let ExprKind::Closure { body, .. } = filter_arg.kind;
|
||||
let body = cx.tcx.hir().body(body);
|
||||
if let [param] = body.params;
|
||||
if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind;
|
||||
if let ExprKind::Binary(ref op, l, r) = body.value.kind;
|
||||
|
|
|
@ -514,7 +514,7 @@ fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId,
|
|||
| ExprKind::Loop(..)
|
||||
| ExprKind::Match(..)
|
||||
| ExprKind::Let(..)
|
||||
| ExprKind::Closure(..)
|
||||
| ExprKind::Closure{..}
|
||||
| ExprKind::Block(..)
|
||||
| ExprKind::Assign(..)
|
||||
| ExprKind::AssignOp(..)
|
||||
|
|
|
@ -44,7 +44,7 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
|
|||
diagnostic.span_suggestion_hidden(
|
||||
span_after_ident,
|
||||
"remove the brackets",
|
||||
";".to_string(),
|
||||
";",
|
||||
Applicability::MachineApplicable);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -50,8 +50,8 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
|
|||
.tcx
|
||||
.const_eval_poly(def_id.to_def_id())
|
||||
.ok()
|
||||
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
|
||||
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
|
||||
if let ty::Adt(adt, _) = ty.kind() {
|
||||
if adt.is_enum() {
|
||||
ty = adt.repr().discr_type().to_ty(cx.tcx);
|
||||
|
|
|
@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
|||
return;
|
||||
}
|
||||
let body = match expr.kind {
|
||||
ExprKind::Closure(_, _, id, _, _) => cx.tcx.hir().body(id),
|
||||
ExprKind::Closure { body, .. } => cx.tcx.hir().body(body),
|
||||
_ => return,
|
||||
};
|
||||
if body.value.span.from_expansion() {
|
||||
|
|
|
@ -159,8 +159,8 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
|
|||
}
|
||||
}
|
||||
if method.ident.name == sym!(flat_map) && args.len() == 2 {
|
||||
if let ExprKind::Closure(_, _, body_id, _, _) = args[1].kind {
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
if let ExprKind::Closure { body, .. } = args[1].kind {
|
||||
let body = cx.tcx.hir().body(body);
|
||||
return is_infinite(cx, &body.value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ use if_chain::if_chain;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, ConstKind};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
|
@ -54,8 +53,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
|
|||
if let ItemKind::Const(hir_ty, _) = &item.kind;
|
||||
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
|
||||
if let ty::Array(element_type, cst) = ty.kind();
|
||||
if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val();
|
||||
if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
|
||||
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
|
||||
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
|
||||
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
|
||||
if self.maximum_allowed_size < element_count * element_size;
|
||||
|
||||
|
@ -76,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
|
|||
diag.span_suggestion(
|
||||
sugg_span,
|
||||
"make this a static item",
|
||||
"static".to_string(),
|
||||
"static",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ use clippy_utils::source::snippet;
|
|||
use if_chain::if_chain;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, ConstKind};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
|
@ -43,8 +42,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
|
|||
if_chain! {
|
||||
if let ExprKind::Repeat(_, _) = expr.kind;
|
||||
if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind();
|
||||
if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val();
|
||||
if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
|
||||
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
|
||||
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
|
||||
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
|
||||
if self.maximum_allowed_size < element_count * element_size;
|
||||
then {
|
||||
|
|
|
@ -369,8 +369,8 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
|
|||
self.visit_expr(expr);
|
||||
}
|
||||
},
|
||||
ExprKind::Closure(_, _, body_id, ..) => {
|
||||
let body = self.cx.tcx.hir().body(body_id);
|
||||
ExprKind::Closure { body, .. } => {
|
||||
let body = self.cx.tcx.hir().body(body);
|
||||
self.visit_expr(&body.value);
|
||||
},
|
||||
_ => walk_expr(self, expr),
|
||||
|
|
|
@ -188,7 +188,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
|
|||
})
|
||||
.fold(NeverLoopResult::Otherwise, combine_both),
|
||||
ExprKind::Yield(_, _)
|
||||
| ExprKind::Closure(_, _, _, _, _)
|
||||
| ExprKind::Closure { .. }
|
||||
| ExprKind::Path(_)
|
||||
| ExprKind::ConstBlock(_)
|
||||
| ExprKind::Lit(_)
|
||||
|
|
|
@ -220,7 +220,7 @@ fn uses_iter<'tcx>(cx: &LateContext<'tcx>, iter_expr: &IterExpr, container: &'tc
|
|||
if let Some(e) = e {
|
||||
self.visit_expr(e);
|
||||
}
|
||||
} else if let ExprKind::Closure(_, _, id, _, _) = e.kind {
|
||||
} else if let ExprKind::Closure { body: id, .. } = e.kind {
|
||||
if is_res_used(self.cx, self.iter_expr.path, id) {
|
||||
self.uses_iter = true;
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
|
|||
if let Some(e) = e {
|
||||
self.visit_expr(e);
|
||||
}
|
||||
} else if let ExprKind::Closure(_, _, id, _, _) = e.kind {
|
||||
} else if let ExprKind::Closure { body: id, .. } = e.kind {
|
||||
self.used_iter = is_res_used(self.cx, self.iter_expr.path, id);
|
||||
} else {
|
||||
walk_expr(self, e);
|
||||
|
@ -307,7 +307,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
|
|||
if let Some(e) = e {
|
||||
self.visit_expr(e);
|
||||
}
|
||||
} else if let ExprKind::Closure(_, _, id, _, _) = e.kind {
|
||||
} else if let ExprKind::Closure { body: id, .. } = e.kind {
|
||||
self.used_after = is_res_used(self.cx, self.iter_expr.path, id);
|
||||
} else {
|
||||
walk_expr(self, e);
|
||||
|
|
|
@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
|
|||
diag.span_suggestion(
|
||||
block.span,
|
||||
"move the body of the async block to the enclosing function",
|
||||
body_snip.to_string(),
|
||||
body_snip,
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
}
|
||||
|
@ -177,8 +177,8 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
|
|||
if let Some(block_expr) = block.expr;
|
||||
if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR);
|
||||
if args.len() == 1;
|
||||
if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
if let Expr{kind: ExprKind::Closure { body, .. }, ..} = args[0];
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
|
||||
then {
|
||||
return Some(closure_body);
|
||||
|
|
|
@ -88,8 +88,8 @@ fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
|
|||
}
|
||||
}
|
||||
if_chain! {
|
||||
if let ExprKind::Closure(_, _, body_id, ..) = map_expr.kind;
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
if let ExprKind::Closure { body, .. } = map_expr.kind;
|
||||
let body = cx.tcx.hir().body(body);
|
||||
if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
|
||||
if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind;
|
||||
if is_lang_ctor(cx, ok_path, ResultOk);
|
||||
|
|
|
@ -67,9 +67,9 @@ impl<'tcx> LateLintPass<'tcx> for MapClone {
|
|||
if method.ident.name == sym::map;
|
||||
let ty = cx.typeck_results().expr_ty(&args[0]);
|
||||
if is_type_diagnostic_item(cx, ty, sym::Option) || is_trait_method(cx, e, sym::Iterator);
|
||||
if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind;
|
||||
if let hir::ExprKind::Closure { body, .. } = args[1].kind;
|
||||
then {
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
let closure_expr = peel_blocks(&closure_body.value);
|
||||
match closure_body.params[0].pat.kind {
|
||||
hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
|
||||
|
|
|
@ -117,12 +117,19 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
|
|||
// only work if the method name is `map_err` and there are only 2 arguments (e.g. x.map_err(|_|[1]
|
||||
// Enum::Variant[2]))
|
||||
if method.ident.as_str() == "map_err" && args.len() == 2 {
|
||||
// make sure the first argument is a closure, and grab the CaptureRef, body_id, and body_span fields
|
||||
if let ExprKind::Closure(capture, _, body_id, body_span, _) = args[1].kind {
|
||||
// make sure the first argument is a closure, and grab the CaptureRef, BodyId, and fn_decl_span
|
||||
// fields
|
||||
if let ExprKind::Closure {
|
||||
capture_clause,
|
||||
body,
|
||||
fn_decl_span,
|
||||
..
|
||||
} = args[1].kind
|
||||
{
|
||||
// check if this is by Reference (meaning there's no move statement)
|
||||
if capture == CaptureBy::Ref {
|
||||
if capture_clause == CaptureBy::Ref {
|
||||
// Get the closure body to check the parameters and values
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
// make sure there's only one parameter (`|_|`)
|
||||
if closure_body.params.len() == 1 {
|
||||
// make sure that parameter is the wild token (`_`)
|
||||
|
@ -132,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
|
|||
span_lint_and_help(
|
||||
cx,
|
||||
MAP_ERR_IGNORE,
|
||||
body_span,
|
||||
fn_decl_span,
|
||||
"`map_err(|_|...` wildcard pattern discards the original error",
|
||||
None,
|
||||
"consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
|
||||
|
|
|
@ -169,12 +169,12 @@ fn unit_closure<'tcx>(
|
|||
expr: &hir::Expr<'_>,
|
||||
) -> Option<(&'tcx hir::Param<'tcx>, &'tcx hir::Expr<'tcx>)> {
|
||||
if_chain! {
|
||||
if let hir::ExprKind::Closure(_, decl, inner_expr_id, _, _) = expr.kind;
|
||||
let body = cx.tcx.hir().body(inner_expr_id);
|
||||
if let hir::ExprKind::Closure { fn_decl, body, .. } = expr.kind;
|
||||
let body = cx.tcx.hir().body(body);
|
||||
let body_expr = &body.value;
|
||||
if decl.inputs.len() == 1;
|
||||
if fn_decl.inputs.len() == 1;
|
||||
if is_unit_expression(cx, body_expr);
|
||||
if let Some(binding) = iter_input_pats(decl, body).next();
|
||||
if let Some(binding) = iter_input_pats(fn_decl, body).next();
|
||||
then {
|
||||
return Some((binding, body_expr));
|
||||
}
|
||||
|
|
|
@ -110,14 +110,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
|||
arm1.span,
|
||||
"this match arm has an identical body to the `_` wildcard arm",
|
||||
|diag| {
|
||||
diag.span_suggestion(
|
||||
arm1.span,
|
||||
"try removing the arm",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.help("or try changing either arm body")
|
||||
.span_note(arm2.span, "`_` wildcard arm here");
|
||||
diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect)
|
||||
.help("or try changing either arm body")
|
||||
.span_note(arm2.span, "`_` wildcard arm here");
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -177,7 +177,7 @@ fn sugg_with_curlies<'a>(
|
|||
|
||||
let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
|
||||
if let Some(parent_expr) = get_parent_expr(cx, match_expr) {
|
||||
if let ExprKind::Closure(..) = parent_expr.kind {
|
||||
if let ExprKind::Closure { .. } = parent_expr.kind {
|
||||
cbrace_end = format!("\n{}}}", indent);
|
||||
// Fix body indent due to the closure
|
||||
indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
|
||||
|
|
|
@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_note;
|
|||
use core::cmp::Ordering;
|
||||
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -34,11 +35,25 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
|||
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
||||
let lhs_const = match lhs {
|
||||
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
|
||||
None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
|
||||
None => {
|
||||
let min_val_const = ty.numeric_min_val(cx.tcx)?;
|
||||
let min_constant = mir::ConstantKind::from_value(
|
||||
cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
|
||||
ty,
|
||||
);
|
||||
miri_to_const(cx.tcx, min_constant)?
|
||||
},
|
||||
};
|
||||
let rhs_const = match rhs {
|
||||
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
|
||||
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
|
||||
None => {
|
||||
let max_val_const = ty.numeric_max_val(cx.tcx)?;
|
||||
let max_constant = mir::ConstantKind::from_value(
|
||||
cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
|
||||
ty,
|
||||
);
|
||||
miri_to_const(cx.tcx, max_constant)?
|
||||
},
|
||||
};
|
||||
let lhs_val = lhs_const.int_value(cx, ty)?;
|
||||
let rhs_val = rhs_const.int_value(cx, ty)?;
|
||||
|
|
|
@ -70,7 +70,7 @@ fn temporaries_need_ordered_drop<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<
|
|||
}
|
||||
}
|
||||
},
|
||||
// the base type is alway taken by reference.
|
||||
// the base type is always taken by reference.
|
||||
// e.g. In `(vec![0])[0]` the vector is a temporary value.
|
||||
ExprKind::Index(base, index) => {
|
||||
if !matches!(base.kind, ExprKind::Path(_)) {
|
||||
|
|
|
@ -305,7 +305,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
|
|||
ExprKind::Break(_, _) |
|
||||
ExprKind::Cast(_, _) |
|
||||
// Don't want to check the closure itself, only invocation, which is covered by MethodCall
|
||||
ExprKind::Closure(_, _, _, _, _) |
|
||||
ExprKind::Closure { .. } |
|
||||
ExprKind::ConstBlock(_) |
|
||||
ExprKind::Continue(_) |
|
||||
ExprKind::DropTemps(_) |
|
||||
|
|
|
@ -150,11 +150,11 @@ pub(crate) trait BindInsteadOfMap {
|
|||
}
|
||||
|
||||
match arg.kind {
|
||||
hir::ExprKind::Closure(_, _, body_id, closure_args_span, _) => {
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
hir::ExprKind::Closure { body, fn_decl_span, .. } => {
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
let closure_expr = peel_blocks(&closure_body.value);
|
||||
|
||||
if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, closure_args_span) {
|
||||
if Self::lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) {
|
||||
true
|
||||
} else {
|
||||
Self::lint_closure(cx, expr, closure_expr)
|
||||
|
|
|
@ -22,8 +22,8 @@ fn is_method<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Sy
|
|||
hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
|
||||
segments.segments.last().unwrap().ident.name == method_name
|
||||
},
|
||||
hir::ExprKind::Closure(_, _, c, _, _) => {
|
||||
let body = cx.tcx.hir().body(*c);
|
||||
hir::ExprKind::Closure { body, .. } => {
|
||||
let body = cx.tcx.hir().body(*body);
|
||||
let closure_expr = peel_blocks(&body.value);
|
||||
let arg_id = body.params[0].pat.hir_id;
|
||||
match closure_expr.kind {
|
||||
|
@ -106,7 +106,7 @@ pub(super) fn check<'tcx>(
|
|||
if is_trait_method(cx, map_recv, sym::Iterator);
|
||||
|
||||
// filter(|x| ...is_some())...
|
||||
if let ExprKind::Closure(_, _, filter_body_id, ..) = filter_arg.kind;
|
||||
if let ExprKind::Closure { body: filter_body_id, .. } = filter_arg.kind;
|
||||
let filter_body = cx.tcx.hir().body(filter_body_id);
|
||||
if let [filter_param] = filter_body.params;
|
||||
// optional ref pattern: `filter(|&x| ..)`
|
||||
|
@ -129,7 +129,7 @@ pub(super) fn check<'tcx>(
|
|||
if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
|
||||
|
||||
// ...map(|x| ...unwrap())
|
||||
if let ExprKind::Closure(_, _, map_body_id, ..) = map_arg.kind;
|
||||
if let ExprKind::Closure { body: map_body_id, .. } = map_arg.kind;
|
||||
let map_body = cx.tcx.hir().body(map_body_id);
|
||||
if let [map_param] = map_body.params;
|
||||
if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
|
||||
|
|
|
@ -51,8 +51,8 @@ pub(super) fn check<'tcx>(
|
|||
.map_or(false, |fun_def_id| {
|
||||
deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
|
||||
}),
|
||||
hir::ExprKind::Closure(_, _, body_id, _, _) => {
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
hir::ExprKind::Closure { body, .. } => {
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
let closure_expr = peel_blocks(&closure_body.value);
|
||||
|
||||
match &closure_expr.kind {
|
||||
|
|
|
@ -71,27 +71,26 @@ pub(super) fn check<'tcx>(
|
|||
if is_option {
|
||||
let self_snippet = snippet(cx, recv.span, "..");
|
||||
if_chain! {
|
||||
if let hir::ExprKind::Closure(_, _, id, span, _) = map_arg.kind;
|
||||
let arg_snippet = snippet(cx, span, "..");
|
||||
let body = cx.tcx.hir().body(id);
|
||||
if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);
|
||||
if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
|
||||
if Some(id) == cx.tcx.lang_items().option_some_variant();
|
||||
then {
|
||||
let func_snippet = snippet(cx, arg_char.span, "..");
|
||||
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
|
||||
`map(..)` instead";
|
||||
return span_lint_and_sugg(
|
||||
cx,
|
||||
OPTION_MAP_OR_NONE,
|
||||
expr.span,
|
||||
msg,
|
||||
"try using `map` instead",
|
||||
format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Closure { body, fn_decl_span, .. } = map_arg.kind;
|
||||
let arg_snippet = snippet(cx, fn_decl_span, "..");
|
||||
let body = cx.tcx.hir().body(body);
|
||||
if let Some((func, [arg_char])) = reduce_unit_expression(&body.value);
|
||||
if let Some(id) = path_def_id(cx, func).map(|ctor_id| cx.tcx.parent(ctor_id));
|
||||
if Some(id) == cx.tcx.lang_items().option_some_variant();
|
||||
then {
|
||||
let func_snippet = snippet(cx, arg_char.span, "..");
|
||||
let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
|
||||
`map(..)` instead";
|
||||
return span_lint_and_sugg(
|
||||
cx,
|
||||
OPTION_MAP_OR_NONE,
|
||||
expr.span,
|
||||
msg,
|
||||
"try using `map` instead",
|
||||
format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let func_snippet = snippet(cx, map_arg.span, "..");
|
||||
|
|
|
@ -41,8 +41,8 @@ pub(super) fn check<'tcx>(
|
|||
let mut applicability = Applicability::MachineApplicable;
|
||||
let any_search_snippet = if_chain! {
|
||||
if search_method == "find";
|
||||
if let hir::ExprKind::Closure(_, _, body_id, ..) = search_arg.kind;
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
if let hir::ExprKind::Closure { body, .. } = search_arg.kind;
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
if let Some(closure_arg) = closure_body.params.get(0);
|
||||
then {
|
||||
if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
|
||||
|
|
|
@ -176,13 +176,13 @@ fn check_manual_split_once_indirect(
|
|||
diag.span_suggestion(
|
||||
first.span,
|
||||
&remove_msg,
|
||||
String::new(),
|
||||
"",
|
||||
app,
|
||||
);
|
||||
diag.span_suggestion(
|
||||
second.span,
|
||||
&remove_msg,
|
||||
String::new(),
|
||||
"",
|
||||
app,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -18,8 +18,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
|
|||
return;
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Closure(_, _, body_id, ..) = arg.kind {
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
if let hir::ExprKind::Closure { body, .. } = arg.kind {
|
||||
let body = cx.tcx.hir().body(body);
|
||||
let arg_id = body.params[0].pat.hir_id;
|
||||
let mutates_arg =
|
||||
mutated_variables(&body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id));
|
||||
|
|
|
@ -29,8 +29,8 @@ pub(super) fn check(
|
|||
) {
|
||||
if_chain! {
|
||||
// Extract the body of the closure passed to fold
|
||||
if let hir::ExprKind::Closure(_, _, body_id, _, _) = acc.kind;
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
if let hir::ExprKind::Closure { body, .. } = acc.kind;
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
let closure_expr = peel_blocks(&closure_body.value);
|
||||
|
||||
// Check if the closure body is of the form `acc <op> some_expr(x)`
|
||||
|
|
|
@ -85,7 +85,7 @@ pub fn check_for_loop_iter(
|
|||
match addr_of_expr.kind {
|
||||
ExprKind::AddrOf(_, _, referent) => {
|
||||
let span = addr_of_expr.span.with_hi(referent.span.lo());
|
||||
diag.span_suggestion(span, "remove this `&`", String::new(), applicability);
|
||||
diag.span_suggestion(span, "remove this `&`", "", applicability);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ pub(super) fn check<'tcx>(
|
|||
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
|
||||
|
||||
if is_option || is_result {
|
||||
if let hir::ExprKind::Closure(_, _, eid, _, _) = arg.kind {
|
||||
let body = cx.tcx.hir().body(eid);
|
||||
if let hir::ExprKind::Closure { body, .. } = arg.kind {
|
||||
let body = cx.tcx.hir().body(body);
|
||||
let body_expr = &body.value;
|
||||
|
||||
if usage::BindingUsageFinder::are_params_used(cx, body) {
|
||||
|
|
|
@ -114,7 +114,7 @@ struct DivergenceVisitor<'a, 'tcx> {
|
|||
impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
||||
fn maybe_walk_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||
match e.kind {
|
||||
ExprKind::Closure(..) => {},
|
||||
ExprKind::Closure { .. } => {},
|
||||
ExprKind::Match(e, arms, _) => {
|
||||
self.visit_expr(e);
|
||||
for arm in arms {
|
||||
|
@ -245,7 +245,7 @@ fn check_expr<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr<'_>) -
|
|||
walk_expr(vis, expr);
|
||||
}
|
||||
},
|
||||
ExprKind::Closure(_, _, _, _, _) => {
|
||||
ExprKind::Closure { .. } => {
|
||||
// Either
|
||||
//
|
||||
// * `var` is defined in the closure body, in which case we've reached the top of the enclosing
|
||||
|
@ -317,7 +317,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
|
|||
// We're about to descend a closure. Since we don't know when (or
|
||||
// if) the closure will be evaluated, any reads in it might not
|
||||
// occur here (or ever). Like above, bail to avoid false positives.
|
||||
ExprKind::Closure(_, _, _, _, _) |
|
||||
ExprKind::Closure{..} |
|
||||
|
||||
// We want to avoid a false positive when a variable name occurs
|
||||
// only to have its address taken, so we stop here. Technically,
|
||||
|
|
|
@ -72,8 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
|
|||
if has_iter_method(cx, cx.typeck_results().expr_ty(iter_recv)).is_some();
|
||||
// Skip the lint if the body is not block because this is simpler than `for` loop.
|
||||
// e.g. `v.iter().for_each(f)` is simpler and clearer than using `for` loop.
|
||||
if let ExprKind::Closure(_, _, body_id, ..) = for_each_arg.kind;
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
if let ExprKind::Closure { body, .. } = for_each_arg.kind;
|
||||
let body = cx.tcx.hir().body(body);
|
||||
if let ExprKind::Block(..) = body.value.kind;
|
||||
then {
|
||||
let mut ret_collector = RetCollector::default();
|
||||
|
|
|
@ -281,7 +281,7 @@ fn check<'tcx>(
|
|||
diag.tool_only_span_suggestion(
|
||||
local_stmt.span,
|
||||
"remove the local",
|
||||
String::new(),
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
|
@ -318,7 +318,7 @@ fn check<'tcx>(
|
|||
diag.span_suggestion(
|
||||
usage.stmt.span.shrink_to_hi(),
|
||||
"add a semicolon after the `if` expression",
|
||||
";".to_string(),
|
||||
";",
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ fn check<'tcx>(
|
|||
diag.span_suggestion(
|
||||
usage.stmt.span.shrink_to_hi(),
|
||||
"add a semicolon after the `match` expression",
|
||||
";".to_string(),
|
||||
";",
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
|||
diag.span_suggestion(
|
||||
input.span,
|
||||
"consider changing the type to",
|
||||
"&str".to_string(),
|
||||
"&str",
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
return false;
|
||||
}
|
||||
match peel_blocks(expr).kind {
|
||||
ExprKind::Lit(..) | ExprKind::Closure(..) => true,
|
||||
ExprKind::Lit(..) | ExprKind::Closure { .. } => true,
|
||||
ExprKind::Path(..) => !has_drop(cx, cx.typeck_results().expr_ty(expr)),
|
||||
ExprKind::Index(a, b) | ExprKind::Binary(_, a, b) => has_no_effect(cx, a) && has_no_effect(cx, b),
|
||||
ExprKind::Array(v) | ExprKind::Tup(v) => v.iter().all(|val| has_no_effect(cx, val)),
|
||||
|
|
|
@ -13,9 +13,10 @@ use rustc_hir::{
|
|||
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, Lint};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_middle::ty::{self, Const, Ty};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::{InnerSpan, Span, DUMMY_SP};
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
|
@ -142,19 +143,18 @@ fn is_value_unfrozen_raw<'tcx>(
|
|||
result: Result<ConstValue<'tcx>, ErrorHandled>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
|
||||
fn inner<'tcx>(cx: &LateContext<'tcx>, val: mir::ConstantKind<'tcx>) -> bool {
|
||||
match val.ty().kind() {
|
||||
// the fact that we have to dig into every structs to search enums
|
||||
// leads us to the point checking `UnsafeCell` directly is the only option.
|
||||
ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
|
||||
ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
|
||||
let val = cx.tcx.destructure_const(cx.param_env.and(val));
|
||||
let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
|
||||
val.fields.iter().any(|field| inner(cx, *field))
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
result.map_or_else(
|
||||
|err| {
|
||||
// Consider `TooGeneric` cases as being unfrozen.
|
||||
|
@ -180,7 +180,7 @@ fn is_value_unfrozen_raw<'tcx>(
|
|||
// I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
|
||||
err == ErrorHandled::TooGeneric
|
||||
},
|
||||
|val| inner(cx, Const::from_value(cx.tcx, val, ty)),
|
||||
|val| inner(cx, mir::ConstantKind::from_value(val, ty)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -298,8 +298,8 @@ impl<'tcx> Visitor<'tcx> for SideEffectVisit<'tcx> {
|
|||
},
|
||||
ExprKind::Match(expr, arms, _) => self.visit_match(expr, arms),
|
||||
// since analysing the closure is not easy, just set all variables in it to side-effect
|
||||
ExprKind::Closure(_, _, body_id, _, _) => {
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
ExprKind::Closure { body, .. } => {
|
||||
let body = self.tcx.hir().body(body);
|
||||
self.visit_body(body);
|
||||
let vars = std::mem::take(&mut self.ret_vars);
|
||||
self.add_side_effect(vars);
|
||||
|
|
|
@ -255,7 +255,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
|
|||
diag.span_suggestion(
|
||||
sugg_span,
|
||||
"remove this",
|
||||
String::new(),
|
||||
"",
|
||||
app,
|
||||
);
|
||||
if clone_usage.cloned_used {
|
||||
|
|
|
@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
|
|||
if_chain! {
|
||||
if let hir::StmtKind::Local(local) = w[0].kind;
|
||||
if let Option::Some(t) = local.init;
|
||||
if let hir::ExprKind::Closure(..) = t.kind;
|
||||
if let hir::ExprKind::Closure { .. } = t.kind;
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
|
||||
if let hir::StmtKind::Semi(second) = w[1].kind;
|
||||
if let hir::ExprKind::Assign(_, call, _) = second.kind;
|
||||
|
|
|
@ -55,7 +55,7 @@ pub(super) fn check<'tcx>(
|
|||
sugg
|
||||
};
|
||||
|
||||
diag.span_suggestion(e.span, "consider using", sugg.to_string(), Applicability::Unspecified);
|
||||
diag.span_suggestion(e.span, "consider using", sugg, Applicability::Unspecified);
|
||||
},
|
||||
);
|
||||
true
|
||||
|
|
|
@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
|
|||
|diag| {
|
||||
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
let sugg = arg.as_ty(cx.tcx.mk_ptr(*to_ty));
|
||||
diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified);
|
||||
diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -73,7 +73,7 @@ pub(super) fn check<'tcx>(
|
|||
diag.span_suggestion(
|
||||
e.span,
|
||||
"try",
|
||||
sugg.to_string(),
|
||||
sugg,
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
},
|
||||
|
|
|
@ -46,7 +46,7 @@ pub(super) fn check<'tcx>(
|
|||
arg.as_ty(cx.tcx.mk_ptr(rty_and_mut)).as_ty(to_ty)
|
||||
};
|
||||
|
||||
diag.span_suggestion(e.span, "try", sugg.to_string(), Applicability::Unspecified);
|
||||
diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -61,12 +61,7 @@ pub(super) fn check<'tcx>(
|
|||
"transmute from an integer to a pointer",
|
||||
|diag| {
|
||||
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
diag.span_suggestion(
|
||||
e.span,
|
||||
"try",
|
||||
arg.as_ty(&to_ty.to_string()).to_string(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
diag.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()), Applicability::Unspecified);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -116,13 +116,13 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
|
|||
|
||||
fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Span, Option<Span>)> {
|
||||
if_chain! {
|
||||
if let ExprKind::Closure(_, _fn_decl, body_id, span, _) = arg.kind;
|
||||
if let ExprKind::Closure { body, fn_decl_span, .. } = arg.kind;
|
||||
if let ty::Closure(_def_id, substs) = &cx.typeck_results().node_type(arg.hir_id).kind();
|
||||
let ret_ty = substs.as_closure().sig().output();
|
||||
let ty = cx.tcx.erase_late_bound_regions(ret_ty);
|
||||
if ty.is_unit();
|
||||
then {
|
||||
let body = cx.tcx.hir().body(body_id);
|
||||
let body = cx.tcx.hir().body(body);
|
||||
if_chain! {
|
||||
if let ExprKind::Block(block, _) = body.value.kind;
|
||||
if block.expr.is_none();
|
||||
|
@ -131,9 +131,9 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
|
|||
then {
|
||||
let data = stmt.span.data();
|
||||
// Make a span out of the semicolon for the help message
|
||||
Some((span, Some(data.with_lo(data.hi-BytePos(1)))))
|
||||
Some((fn_decl_span, Some(data.with_lo(data.hi-BytePos(1)))))
|
||||
} else {
|
||||
Some((span, None))
|
||||
Some((fn_decl_span, None))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||
use rustc_hir::{Expr, ExprKind, PatKind, Stmt, StmtKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Ty, TypeFoldable, TypeVisitor};
|
||||
use rustc_middle::ty::{self, Ty, TypeFoldable, TypeSuperFoldable, TypeVisitor};
|
||||
|
||||
use super::LET_UNIT_VALUE;
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
|
|||
if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind;
|
||||
if let name = name_ident.ident.name.to_ident_string();
|
||||
if name == "sort_by" || name == "sort_unstable_by";
|
||||
if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args;
|
||||
if let [vec, Expr { kind: ExprKind::Closure{ body: closure_body_id, .. }, .. }] = args;
|
||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::Vec);
|
||||
if let closure_body = cx.tcx.hir().body(*closure_body_id);
|
||||
if let &[
|
||||
|
|
|
@ -466,7 +466,13 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
self.expr(scrutinee);
|
||||
self.slice(arms, |arm| self.arm(arm));
|
||||
},
|
||||
ExprKind::Closure(capture_by, fn_decl, body_id, _, movability) => {
|
||||
ExprKind::Closure {
|
||||
capture_clause,
|
||||
fn_decl,
|
||||
body: body_id,
|
||||
movability,
|
||||
..
|
||||
} => {
|
||||
let movability = OptionPat::new(movability.map(|m| format!("Movability::{m:?}")));
|
||||
|
||||
let ret_ty = match fn_decl.output {
|
||||
|
@ -475,7 +481,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
};
|
||||
|
||||
bind!(self, fn_decl, body_id);
|
||||
kind!("Closure(CaptureBy::{capture_by:?}, {fn_decl}, {body_id}, _, {movability})");
|
||||
kind!("Closure(CaptureBy::{capture_clause:?}, {fn_decl}, {body_id}, _, {movability})");
|
||||
out!("if let {ret_ty} = {fn_decl}.output;");
|
||||
self.body(body_id);
|
||||
},
|
||||
|
|
|
@ -664,8 +664,8 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
|
|||
if let ExprKind::Call(func, and_then_args) = expr.kind;
|
||||
if is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]);
|
||||
if and_then_args.len() == 5;
|
||||
if let ExprKind::Closure(_, _, body_id, _, _) = &and_then_args[4].kind;
|
||||
let body = cx.tcx.hir().body(*body_id);
|
||||
if let ExprKind::Closure { body, .. } = &and_then_args[4].kind;
|
||||
let body = cx.tcx.hir().body(*body);
|
||||
let only_expr = peel_blocks_with_stmt(&body.value);
|
||||
if let ExprKind::MethodCall(ps, span_call_args, _) = &only_expr.kind;
|
||||
then {
|
||||
|
|
|
@ -954,9 +954,9 @@ fn resolve_applicability<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hi
|
|||
}
|
||||
|
||||
fn check_is_multi_part<'hir>(cx: &LateContext<'hir>, closure_expr: &'hir hir::Expr<'hir>) -> bool {
|
||||
if let ExprKind::Closure(_, _, body_id, _, _) = closure_expr.kind {
|
||||
if let ExprKind::Closure { body, .. } = closure_expr.kind {
|
||||
let mut scanner = IsMultiSpanScanner::new(cx);
|
||||
intravisit::walk_body(&mut scanner, cx.tcx.hir().body(body_id));
|
||||
intravisit::walk_body(&mut scanner, cx.tcx.hir().body(body));
|
||||
return scanner.is_multi_part();
|
||||
} else if let Some(local) = get_parent_local(cx, closure_expr) {
|
||||
if let Some(local_init) = local.init {
|
||||
|
|
|
@ -92,7 +92,7 @@ pub fn get_attr<'a>(
|
|||
diag.span_suggestion(
|
||||
attr_segments[1].ident.span,
|
||||
"consider using",
|
||||
new_name.to_string(),
|
||||
new_name,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
diag.emit();
|
||||
|
|
|
@ -7,6 +7,7 @@ use rustc_data_structures::sync::Lrc;
|
|||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
|
||||
|
@ -429,8 +430,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
None,
|
||||
)
|
||||
.ok()
|
||||
.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
|
||||
let result = miri_to_const(result);
|
||||
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
|
||||
let result = miri_to_const(self.lcx.tcx, result);
|
||||
if result.is_some() {
|
||||
self.needed_resolution = true;
|
||||
}
|
||||
|
@ -580,10 +581,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
|
||||
pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant> {
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
match result.val() {
|
||||
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
|
||||
match result {
|
||||
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => {
|
||||
match result.ty().kind() {
|
||||
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
|
||||
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
|
||||
|
@ -603,7 +604,7 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
|
|||
_ => None,
|
||||
}
|
||||
},
|
||||
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty().kind() {
|
||||
mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
|
||||
ty::Ref(_, tam, _) => match tam.kind() {
|
||||
ty::Str => String::from_utf8(
|
||||
data.inner()
|
||||
|
@ -616,12 +617,12 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
|
|||
},
|
||||
_ => None,
|
||||
},
|
||||
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty().kind() {
|
||||
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
|
||||
ty::Array(sub_type, len) => match sub_type.kind() {
|
||||
ty::Float(FloatTy::F32) => match miri_to_const(*len) {
|
||||
Some(Constant::Int(len)) => alloc
|
||||
ty::Float(FloatTy::F32) => match len.to_valtree().try_to_machine_usize(tcx) {
|
||||
Some(len) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
|
||||
.to_owned()
|
||||
.chunks(4)
|
||||
.map(|chunk| {
|
||||
|
@ -633,10 +634,10 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
|
|||
.map(Constant::Vec),
|
||||
_ => None,
|
||||
},
|
||||
ty::Float(FloatTy::F64) => match miri_to_const(*len) {
|
||||
Some(Constant::Int(len)) => alloc
|
||||
ty::Float(FloatTy::F64) => match len.to_valtree().try_to_machine_usize(tcx) {
|
||||
Some(len) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
|
||||
.to_owned()
|
||||
.chunks(8)
|
||||
.map(|chunk| {
|
||||
|
|
|
@ -198,7 +198,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
|||
| ExprKind::Let(..)
|
||||
| ExprKind::If(..)
|
||||
| ExprKind::Match(..)
|
||||
| ExprKind::Closure(..)
|
||||
| ExprKind::Closure { .. }
|
||||
| ExprKind::Field(..)
|
||||
| ExprKind::Path(_)
|
||||
| ExprKind::AddrOf(..)
|
||||
|
|
|
@ -622,10 +622,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
self.hash_expr(e);
|
||||
self.hash_ty(ty);
|
||||
},
|
||||
ExprKind::Closure(cap, _, eid, _, _) => {
|
||||
std::mem::discriminant(&cap).hash(&mut self.s);
|
||||
ExprKind::Closure {
|
||||
capture_clause, body, ..
|
||||
} => {
|
||||
std::mem::discriminant(&capture_clause).hash(&mut self.s);
|
||||
// closures inherit TypeckResults
|
||||
self.hash_expr(&self.cx.tcx.hir().body(eid).value);
|
||||
self.hash_expr(&self.cx.tcx.hir().body(body).value);
|
||||
},
|
||||
ExprKind::Field(e, ref f) => {
|
||||
self.hash_expr(e);
|
||||
|
|
|
@ -964,7 +964,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
|
|||
self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
|
||||
}
|
||||
},
|
||||
ExprKind::Closure(..) => {
|
||||
ExprKind::Closure { .. } => {
|
||||
let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id();
|
||||
for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
|
||||
let local_id = match capture.place.base {
|
||||
|
@ -1202,7 +1202,7 @@ pub fn get_enclosing_loop_or_closure<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -
|
|||
match node {
|
||||
Node::Expr(
|
||||
e @ Expr {
|
||||
kind: ExprKind::Loop(..) | ExprKind::Closure(..),
|
||||
kind: ExprKind::Loop(..) | ExprKind::Closure { .. },
|
||||
..
|
||||
},
|
||||
) => return Some(e),
|
||||
|
@ -1695,7 +1695,7 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t
|
|||
_,
|
||||
&[
|
||||
Expr {
|
||||
kind: ExprKind::Closure(_, _, body, _, _),
|
||||
kind: ExprKind::Closure { body, .. },
|
||||
..
|
||||
},
|
||||
],
|
||||
|
@ -1782,7 +1782,7 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
|
|||
}
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
|
||||
ExprKind::Closure { body, .. } => is_body_identity_function(cx, cx.tcx.hir().body(body)),
|
||||
_ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ impl<'a> Sugg<'a> {
|
|||
| hir::ExprKind::Box(..)
|
||||
| hir::ExprKind::If(..)
|
||||
| hir::ExprKind::Let(..)
|
||||
| hir::ExprKind::Closure(..)
|
||||
| hir::ExprKind::Closure { .. }
|
||||
| hir::ExprKind::Unary(..)
|
||||
| hir::ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)),
|
||||
hir::ExprKind::Continue(..)
|
||||
|
@ -188,7 +188,7 @@ impl<'a> Sugg<'a> {
|
|||
match expr.kind {
|
||||
ast::ExprKind::AddrOf(..)
|
||||
| ast::ExprKind::Box(..)
|
||||
| ast::ExprKind::Closure(..)
|
||||
| ast::ExprKind::Closure { .. }
|
||||
| ast::ExprKind::If(..)
|
||||
| ast::ExprKind::Let(..)
|
||||
| ast::ExprKind::Unary(..)
|
||||
|
@ -790,8 +790,8 @@ pub struct DerefClosure {
|
|||
///
|
||||
/// note: this only works on single line immutable closures with exactly one input parameter.
|
||||
pub fn deref_closure_args<'tcx>(cx: &LateContext<'_>, closure: &'tcx hir::Expr<'_>) -> Option<DerefClosure> {
|
||||
if let hir::ExprKind::Closure(_, fn_decl, body_id, ..) = closure.kind {
|
||||
let closure_body = cx.tcx.hir().body(body_id);
|
||||
if let hir::ExprKind::Closure { fn_decl, body, .. } = closure.kind {
|
||||
let closure_body = cx.tcx.hir().body(body);
|
||||
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
|
||||
// a type annotation is present if param `kind` is different from `TyKind::Infer`
|
||||
let closure_arg_is_type_annotated_double_ref = if let TyKind::Rptr(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind
|
||||
|
|
|
@ -185,7 +185,7 @@ pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr
|
|||
matches!(
|
||||
node,
|
||||
Node::Expr(Expr {
|
||||
kind: ExprKind::Loop(..) | ExprKind::Closure(..),
|
||||
kind: ExprKind::Loop(..) | ExprKind::Closure { .. },
|
||||
..
|
||||
})
|
||||
)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2022-06-04"
|
||||
channel = "nightly-2022-06-16"
|
||||
components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
|
|
@ -19,6 +19,11 @@ use syn::{
|
|||
parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem, Type,
|
||||
};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn dummy(_args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut item = parse_macro_input!(input as ItemTrait);
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/ice-6256.rs:13:28
|
||||
error[E0521]: borrowed data escapes outside of closure
|
||||
--> $DIR/ice-6256.rs:13:26
|
||||
|
|
||||
LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
|
||||
| ^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected reference `&(dyn TT + 'static)`
|
||||
found reference `&dyn TT`
|
||||
note: the anonymous lifetime #1 defined here...
|
||||
--> $DIR/ice-6256.rs:13:13
|
||||
|
|
||||
LL | let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...does not necessarily outlive the static lifetime
|
||||
| - - ^^^^^^^^
|
||||
| | | |
|
||||
| | | `x` escapes the closure body here
|
||||
| | | argument requires that `'1` must outlive `'static`
|
||||
| | let's call the lifetime of this reference `'1`
|
||||
| `x` is a reference that is only valid in the closure body
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0521`.
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
#![feature(custom_inner_attributes)]
|
||||
#![rustfmt::skip]
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
||||
#[macro_use]
|
||||
extern crate proc_macro_attr;
|
||||
|
||||
|
@ -113,10 +110,10 @@ pub trait Bazz {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
#[clap(after_help = "This ia a help message.
|
||||
#[derive(Clone, Copy)]
|
||||
#[dummy(string = "first line
|
||||
|
||||
You're welcome.
|
||||
second line
|
||||
")]
|
||||
pub struct Args;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:14:1
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:11:1
|
||||
|
|
||||
LL | / #[crate_type = "lib"]
|
||||
LL | |
|
||||
|
@ -10,7 +10,7 @@ LL | | fn with_one_newline_and_comment() { assert!(true) }
|
|||
= note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`
|
||||
|
||||
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:26:1
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:23:1
|
||||
|
|
||||
LL | / #[crate_type = "lib"]
|
||||
LL | |
|
||||
|
@ -18,7 +18,7 @@ LL | | fn with_one_newline() { assert!(true) }
|
|||
| |_
|
||||
|
||||
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:31:1
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:28:1
|
||||
|
|
||||
LL | / #[crate_type = "lib"]
|
||||
LL | |
|
||||
|
@ -27,7 +27,7 @@ LL | | fn with_two_newlines() { assert!(true) }
|
|||
| |_
|
||||
|
||||
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:38:1
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:35:1
|
||||
|
|
||||
LL | / #[crate_type = "lib"]
|
||||
LL | |
|
||||
|
@ -35,7 +35,7 @@ LL | | enum Baz {
|
|||
| |_
|
||||
|
||||
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:46:1
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:43:1
|
||||
|
|
||||
LL | / #[crate_type = "lib"]
|
||||
LL | |
|
||||
|
@ -43,7 +43,7 @@ LL | | struct Foo {
|
|||
| |_
|
||||
|
||||
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:54:1
|
||||
--> $DIR/empty_line_after_outer_attribute.rs:51:1
|
||||
|
|
||||
LL | / #[crate_type = "lib"]
|
||||
LL | |
|
||||
|
|
Loading…
Reference in a new issue