Make ExprKind::Closure a struct variant.

This commit is contained in:
Camille GILLOT 2022-06-11 21:25:25 +02:00
parent fa68e73e99
commit 3039cfeb6a
75 changed files with 251 additions and 216 deletions

View File

@ -577,7 +577,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
let decl = self.arena.alloc(hir::FnDecl {
let fn_decl = self.arena.alloc(hir::FnDecl {
inputs: arena_vec![self; input_ty],
output,
c_variadic: false,
@ -598,7 +598,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
let params = arena_vec![self; param];
let body_id = self.lower_body(move |this| {
let body = self.lower_body(move |this| {
this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
let old_ctx = this.task_context;
@ -609,13 +609,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
});
// `static |_task_context| -> <ret_ty> { body }`:
let generator_kind = hir::ExprKind::Closure(
let generator_kind = hir::ExprKind::Closure {
capture_clause,
decl,
body_id,
self.lower_span(span),
Some(hir::Movability::Static),
);
fn_decl,
body,
fn_decl_span: self.lower_span(span),
movability: Some(hir::Movability::Static),
};
let generator = hir::Expr {
hir_id: self.lower_node_id(closure_node_id),
kind: generator_kind,
@ -840,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Expr,
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
let (body_id, generator_option) = self.with_new_scopes(move |this| {
let (body, generator_option) = self.with_new_scopes(move |this| {
let prev = this.current_item;
this.current_item = Some(fn_decl_span);
let mut generator_kind = None;
@ -858,13 +858,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
hir::ExprKind::Closure(
hir::ExprKind::Closure {
capture_clause,
fn_decl,
body_id,
self.lower_span(fn_decl_span),
generator_option,
)
body,
fn_decl_span: self.lower_span(fn_decl_span),
movability: generator_option,
}
}
fn generator_movability_for_fn(
@ -911,7 +911,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
let body_id = self.with_new_scopes(|this| {
let body = self.with_new_scopes(|this| {
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
struct_span_err!(
@ -950,13 +950,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// closure argument types.
let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
hir::ExprKind::Closure(
hir::ExprKind::Closure {
capture_clause,
fn_decl,
body_id,
self.lower_span(fn_decl_span),
None,
)
body,
fn_decl_span: self.lower_span(fn_decl_span),
movability: None,
}
}
/// Destructure the LHS of complex assignments.

View File

@ -896,7 +896,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(local_did);
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
if let hir::ExprKind::Closure { body, fn_decl_span, .. } = expr {
for (captured_place, place) in self
.infcx
.tcx
@ -909,11 +909,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if target_place == place.as_ref() =>
{
debug!("closure_span: found captured local {:?}", place);
let body = self.infcx.tcx.hir().body(*body_id);
let body = self.infcx.tcx.hir().body(*body);
let generator_kind = body.generator_kind();
return Some((
*args_span,
*fn_decl_span,
generator_kind,
captured_place.get_capture_kind_span(self.infcx.tcx),
captured_place.get_path_span(self.infcx.tcx),

View File

@ -311,8 +311,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
// Can't have BrEnv in functions, constants or generators.
bug!("BrEnv outside of closure.");
};
let hir::ExprKind::Closure(_, _, _, args_span, _) =
tcx.hir().expect_expr(self.mir_hir_id()).kind else {
let hir::ExprKind::Closure { fn_decl_span, .. }
= tcx.hir().expect_expr(self.mir_hir_id()).kind
else {
bug!("Closure is not defined by a closure expr");
};
let region_name = self.synthesize_region_name();
@ -336,7 +337,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
Some(RegionName {
name: region_name,
source: RegionNameSource::SynthesizedFreeEnvRegion(
args_span,
fn_decl_span,
note.to_string(),
),
})
@ -683,16 +684,16 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let (return_span, mir_description, hir_ty) = match hir.get(mir_hir_id) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, return_ty, body_id, span, _),
kind: hir::ExprKind::Closure { fn_decl, body, fn_decl_span, .. },
..
}) => {
let (mut span, mut hir_ty) = match return_ty.output {
let (mut span, mut hir_ty) = match fn_decl.output {
hir::FnRetTy::DefaultReturn(_) => {
(tcx.sess.source_map().end_point(*span), None)
(tcx.sess.source_map().end_point(*fn_decl_span), None)
}
hir::FnRetTy::Return(hir_ty) => (return_ty.output.span(), Some(hir_ty)),
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
};
let mir_description = match hir.body(*body_id).generator_kind {
let mir_description = match hir.body(*body).generator_kind {
Some(hir::GeneratorKind::Async(gen)) => match gen {
hir::AsyncGeneratorKind::Block => " of async block",
hir::AsyncGeneratorKind::Closure => " of async closure",
@ -822,8 +823,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let yield_span = match tcx.hir().get(self.mir_hir_id()) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, _, _, span, _), ..
}) => (tcx.sess.source_map().end_point(*span)),
kind: hir::ExprKind::Closure { fn_decl_span, .. },
..
}) => (tcx.sess.source_map().end_point(*fn_decl_span)),
_ => self.body.span,
};

View File

@ -1651,7 +1651,7 @@ impl Expr<'_> {
ExprKind::Let(..) => ExprPrecedence::Let,
ExprKind::Loop(..) => ExprPrecedence::Loop,
ExprKind::Match(..) => ExprPrecedence::Match,
ExprKind::Closure(..) => ExprPrecedence::Closure,
ExprKind::Closure { .. } => ExprPrecedence::Closure,
ExprKind::Block(..) => ExprPrecedence::Block,
ExprKind::Assign(..) => ExprPrecedence::Assign,
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
@ -1711,7 +1711,7 @@ impl Expr<'_> {
| ExprKind::Tup(..)
| ExprKind::If(..)
| ExprKind::Match(..)
| ExprKind::Closure(..)
| ExprKind::Closure { .. }
| ExprKind::Block(..)
| ExprKind::Repeat(..)
| ExprKind::Array(..)
@ -1794,7 +1794,7 @@ impl Expr<'_> {
| ExprKind::Match(..)
| ExprKind::MethodCall(..)
| ExprKind::Call(..)
| ExprKind::Closure(..)
| ExprKind::Closure { .. }
| ExprKind::Block(..)
| ExprKind::Repeat(..)
| ExprKind::Break(..)
@ -1929,7 +1929,13 @@ pub enum ExprKind<'hir> {
///
/// This may also be a generator literal or an `async block` as indicated by the
/// `Option<Movability>`.
Closure(CaptureBy, &'hir FnDecl<'hir>, BodyId, Span, Option<Movability>),
Closure {
capture_clause: CaptureBy,
fn_decl: &'hir FnDecl<'hir>,
body: BodyId,
fn_decl_span: Span,
movability: Option<Movability>,
},
/// A block (e.g., `'label: { ... }`).
Block(&'hir Block<'hir>, Option<Label>),
@ -3455,7 +3461,7 @@ impl<'hir> Node<'hir> {
_ => None,
},
Node::Expr(e) => match e.kind {
ExprKind::Closure(..) => Some(FnKind::Closure),
ExprKind::Closure { .. } => Some(FnKind::Closure),
_ => None,
},
_ => None,

View File

@ -1168,14 +1168,13 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
visitor.visit_expr(subexpression);
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor
.visit_fn(
FnKind::Closure,
function_declaration,
body,
expression.span,
expression.hir_id,
),
ExprKind::Closure {
ref fn_decl,
body,
capture_clause: _,
fn_decl_span: _,
movability: _,
} => visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id),
ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);
visitor.visit_block(block);

View File

@ -1078,7 +1078,9 @@ impl<'a> State<'a> {
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
fn cond_needs_par(expr: &hir::Expr<'_>) -> bool {
match expr.kind {
hir::ExprKind::Break(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) => true,
hir::ExprKind::Break(..) | hir::ExprKind::Closure { .. } | hir::ExprKind::Ret(..) => {
true
}
_ => contains_exterior_struct_lit(expr),
}
}
@ -1455,10 +1457,16 @@ impl<'a> State<'a> {
}
self.bclose(expr.span);
}
hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => {
hir::ExprKind::Closure {
capture_clause,
ref fn_decl,
body,
fn_decl_span: _,
movability: _,
} => {
self.print_capture_clause(capture_clause);
self.print_closure_params(&decl, body);
self.print_closure_params(&fn_decl, body);
self.space();
// This is a bare expression.

View File

@ -991,22 +991,24 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
}
if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
if let (&ExprKind::Closure(_, decl, body_id, span, _), ty::Closure(_, substs)) =
(&expr.kind, node_ty.kind())
if let (
&ExprKind::Closure { fn_decl, body, fn_decl_span, .. },
ty::Closure(_, substs),
) = (&expr.kind, node_ty.kind())
{
let output = substs.as_closure().sig().output().skip_binder();
if self.generic_arg_contains_target(output.into()) {
let body = self.infcx.tcx.hir().body(body_id);
let body = self.infcx.tcx.hir().body(body);
let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
None
} else {
Some(body.value.span.shrink_to_hi())
};
self.update_infer_source(InferSource {
span,
span: fn_decl_span,
kind: InferSourceKind::ClosureReturn {
ty: output,
data: &decl.output,
data: &fn_decl.output,
should_wrap_expr,
},
})

View File

@ -55,7 +55,7 @@ pub fn find_param_with_region<'tcx>(
// Don't perform this on closures
match hir.get(hir_id) {
hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
return None;
}
_ => {}

View File

@ -2030,7 +2030,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
fn encode_info_for_expr(&mut self, expr: &hir::Expr<'_>) {
if let hir::ExprKind::Closure(..) = expr.kind {
if let hir::ExprKind::Closure { .. } = expr.kind {
self.encode_info_for_closure(expr.hir_id);
}
}

View File

@ -22,7 +22,7 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
| Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), .. }) => Some(&sig.decl),
Node::Expr(Expr { kind: ExprKind::Closure(_, fn_decl, ..), .. })
Node::Expr(Expr { kind: ExprKind::Closure { fn_decl, .. }, .. })
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, ..), .. }) => {
Some(fn_decl)
}
@ -54,7 +54,7 @@ pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
..
})
| Node::Expr(Expr { kind: ExprKind::Closure(.., body, _, _), .. }) => Some(*body),
| Node::Expr(Expr { kind: ExprKind::Closure { body, .. }, .. }) => Some(*body),
Node::AnonConst(constant) => Some(constant.body),
@ -285,8 +285,8 @@ impl<'hir> Map<'hir> {
}
Node::Field(_) => DefKind::Field,
Node::Expr(expr) => match expr.kind {
ExprKind::Closure(.., None) => DefKind::Closure,
ExprKind::Closure(.., Some(_)) => DefKind::Generator,
ExprKind::Closure { movability: None, .. } => DefKind::Closure,
ExprKind::Closure { movability: Some(_), .. } => DefKind::Generator,
_ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
},
Node::GenericParam(param) => match param.kind {
@ -758,7 +758,7 @@ impl<'hir> Map<'hir> {
Node::Item(_)
| Node::ForeignItem(_)
| Node::TraitItem(_)
| Node::Expr(Expr { kind: ExprKind::Closure(..), .. })
| Node::Expr(Expr { kind: ExprKind::Closure { .. }, .. })
| Node::ImplItem(_) => return Some(hir_id),
// Ignore `return`s on the first iteration
Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })

View File

@ -1550,7 +1550,7 @@ impl<'tcx> TyCtxt<'tcx> {
Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
Node::Expr(&hir::Expr { kind: ExprKind::Closure(..), .. }) => {}
Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
_ => return None,
}

View File

@ -66,8 +66,8 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
// Figure out what primary body this item has.
let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => {
(*body_id, decl.output.span(), None)
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { fn_decl, body, .. }, .. }) => {
(*body, fn_decl.output.span(), None)
}
Node::Item(hir::Item {
kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),

View File

@ -418,7 +418,7 @@ impl<'tcx> Cx<'tcx> {
}
},
hir::ExprKind::Closure(..) => {
hir::ExprKind::Closure { .. } => {
let closure_ty = self.typeck_results().expr_ty(expr);
let (def_id, substs, movability) = match *closure_ty.kind() {
ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),

View File

@ -2340,7 +2340,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
let target = match expr.kind {
hir::ExprKind::Closure(..) => Target::Closure,
hir::ExprKind::Closure { .. } => Target::Closure,
_ => Target::Expression,
};

View File

@ -405,7 +405,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
}
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Closure(..) => {
hir::ExprKind::Closure { .. } => {
// Interesting control flow (for loops can contain labeled
// breaks or continues)
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
@ -833,7 +833,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::Field(ref e, _) => self.propagate_through_expr(&e, succ),
hir::ExprKind::Closure(..) => {
hir::ExprKind::Closure { .. } => {
debug!("{:?} is an ExprKind::Closure", expr);
// the construction of a closure itself is not important,
@ -1387,7 +1387,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::AddrOf(..)
| hir::ExprKind::Struct(..)
| hir::ExprKind::Repeat(..)
| hir::ExprKind::Closure(..)
| hir::ExprKind::Closure { .. }
| hir::ExprKind::Path(_)
| hir::ExprKind::Yield(..)
| hir::ExprKind::Box(..)

View File

@ -57,14 +57,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
hir::ExprKind::Loop(ref b, _, source, _) => {
self.with_context(Loop(source), |v| v.visit_block(&b));
}
hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => {
hir::ExprKind::Closure { ref fn_decl, body, fn_decl_span, movability, .. } => {
let cx = if let Some(Movability::Static) = movability {
AsyncClosure(span)
AsyncClosure(fn_decl_span)
} else {
Closure(span)
Closure(fn_decl_span)
};
self.visit_fn_decl(&function_decl);
self.with_context(cx, |v| v.visit_nested_body(b));
self.visit_fn_decl(&fn_decl);
self.with_context(cx, |v| v.visit_nested_body(body));
}
hir::ExprKind::Block(ref b, Some(_label)) => {
self.with_context(LabeledBlock, |v| v.visit_block(&b));

View File

@ -212,7 +212,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
| ExprKind::Loop(..)
| ExprKind::Match(..)
| ExprKind::If(..)
| ExprKind::Closure(..)
| ExprKind::Closure { .. }
| ExprKind::Assign(..)
| ExprKind::AssignOp(..)
| ExprKind::Field(..)

View File

@ -273,7 +273,7 @@ impl<'tcx> ReachableContext<'tcx> {
}
hir::ImplItemKind::TyAlias(_) => {}
},
Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., body, _, _), .. }) => {
Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { body, .. }, .. }) => {
self.visit_nested_body(body);
}
// Nothing to recurse on for these

View File

@ -75,7 +75,7 @@ impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Closure(..) = expr.kind {
if let hir::ExprKind::Closure { .. } = expr.kind {
let closure_def_id = self.tcx.hir().local_def_id(expr.hir_id);
if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
// Every capture of a closure expression is a local in scope,

View File

@ -1981,7 +1981,7 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility {
match tcx.hir().get(hir_id) {
// Unique types created for closures participate in type privacy checking.
// They have visibilities inherited from the module they are defined in.
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. })
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure{..}, .. })
// - AST lowering creates dummy `use` items which don't
// get their entries in the resolver's visibility table.
// - AST lowering also creates opaque type items with inherited visibilities.

View File

@ -1360,15 +1360,15 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
}
}
}
hir::ExprKind::Closure(_, ref decl, body, _fn_decl_span, _) => {
hir::ExprKind::Closure { ref fn_decl, body, .. } => {
let id = format!("${}", ex.hir_id);
// walk arg and return types
for ty in decl.inputs {
for ty in fn_decl.inputs {
self.visit_ty(ty);
}
if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
if let hir::FnRetTy::Return(ref ret_ty) = fn_decl.output {
self.visit_ty(ret_ty);
}

View File

@ -1084,11 +1084,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let hir = self.tcx.hir();
Some(match node {
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
kind: hir::ExprKind::Closure { body, fn_decl_span, .. },
..
}) => (
sm.guess_head_span(span),
hir.body(id)
sm.guess_head_span(fn_decl_span),
hir.body(body)
.params
.iter()
.map(|arg| {

View File

@ -103,10 +103,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
})
}),
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
kind: hir::ExprKind::Closure { body, movability, .. },
..
}) => self.describe_generator(*body_id).or_else(|| {
Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
}) => self.describe_generator(*body).or_else(|| {
Some(if movability.is_some() { "an async closure" } else { "a closure" })
}),
hir::Node::Expr(hir::Expr { .. }) => {
let parent_hid = hir.get_parent_node(hir_id);

View File

@ -775,14 +775,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Get the name of the callable and the arguments to be used in the suggestion.
let (snippet, sugg) = match hir.get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, decl, _, span, ..),
kind: hir::ExprKind::Closure { fn_decl, fn_decl_span, .. },
..
})) => {
err.span_label(*span, "consider calling this closure");
err.span_label(*fn_decl_span, "consider calling this closure");
let Some(name) = self.get_closure_name(def_id, err, &msg) else {
return false;
};
let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
let args = fn_decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
let sugg = format!("({})", args);
(format!("{}{}", name, sugg), sugg)
}

View File

@ -283,11 +283,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir_id = self.tcx.hir().get_parent_node(hir_id);
let parent_node = self.tcx.hir().get(hir_id);
if let (
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, _, sp, ..), .. }),
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, .. }, ..
}),
hir::ExprKind::Block(..),
) = (parent_node, callee_node)
{
let start = sp.shrink_to_lo();
let start = fn_decl_span.shrink_to_lo();
let end = callee_span.shrink_to_hi();
err.multipart_suggestion(
"if you meant to create this closure and immediately call it, surround the \

View File

@ -124,7 +124,7 @@ pub(super) fn check_fn<'a, 'tcx>(
..
}) => Some(header),
// Closures are RustCall, but they tuple their arguments, so shouldn't be checked
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
};

View File

@ -1577,8 +1577,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let parent_id = fcx.tcx.hir().get_parent_node(id);
let parent = fcx.tcx.hir().get(parent_id);
if let Some(expr) = expression
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, body_id, ..), .. }) = parent
&& !matches!(fcx.tcx.hir().get(body_id.hir_id), hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(..), .. }))
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { body, .. }, .. }) = parent
&& !matches!(fcx.tcx.hir().body(*body).value.kind, hir::ExprKind::Block(..))
{
fcx.suggest_missing_semicolon(&mut err, expr, expected, true);
}

View File

@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let param_parent = self.tcx.hir().get_parent_node(*param_hir_id);
let Some(Node::Expr(hir::Expr {
hir_id: expr_hir_id,
kind: hir::ExprKind::Closure(_, closure_fn_decl, ..),
kind: hir::ExprKind::Closure { fn_decl: closure_fn_decl, .. },
..
})) = self.tcx.hir().find(param_parent) else {
return None;

View File

@ -319,8 +319,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Match(discrim, arms, match_src) => {
self.check_match(expr, &discrim, arms, expected, match_src)
}
ExprKind::Closure(capture, decl, body_id, _, gen) => {
self.check_expr_closure(expr, capture, &decl, body_id, gen, expected)
ExprKind::Closure { capture_clause, fn_decl, body, movability, .. } => {
self.check_expr_closure(expr, capture_clause, &fn_decl, body, movability, expected)
}
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),

View File

@ -387,7 +387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
continue;
}
let is_closure = matches!(arg.kind, ExprKind::Closure(..));
let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
if is_closure != check_closures {
continue;
}
@ -1774,10 +1774,10 @@ fn label_fn_like<'tcx>(
} else {
match tcx.hir().get_if_local(def_id) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_, _, _, span, ..),
kind: hir::ExprKind::Closure { fn_decl_span, .. },
..
})) => {
let spans: MultiSpan = (*span).into();
let spans: MultiSpan = (*fn_decl_span).into();
// Note: We don't point to param spans here because they overlap
// with the closure span itself

View File

@ -121,7 +121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.join(", ");
}
Some(Node::Expr(hir::Expr {
kind: ExprKind::Closure(_, _, body_id, _, _),
kind: ExprKind::Closure { body: body_id, .. },
span: full_closure_span,
..
})) => {

View File

@ -188,7 +188,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
| ExprKind::If(..)
| ExprKind::Loop(..)
| ExprKind::Match(..)
| ExprKind::Closure(..)
| ExprKind::Closure { .. }
| ExprKind::Block(..)
| ExprKind::Assign(..)
| ExprKind::AssignOp(..)
@ -444,7 +444,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
| ExprKind::Block(..)
| ExprKind::Box(..)
| ExprKind::Cast(..)
| ExprKind::Closure(..)
| ExprKind::Closure { .. }
| ExprKind::ConstBlock(..)
| ExprKind::DropTemps(..)
| ExprKind::Err

View File

@ -335,7 +335,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
match expr.kind {
// Manually recurse over closures and inline consts, because they are the only
// case of nested bodies that share the parent environment.
hir::ExprKind::Closure(.., body, _, _)
hir::ExprKind::Closure { body, .. }
| hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
let body = visitor.tcx.hir().body(body);
visitor.visit_body(body);

View File

@ -142,10 +142,10 @@ struct InferBorrowKindVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
match expr.kind {
hir::ExprKind::Closure(cc, _, body_id, _, _) => {
hir::ExprKind::Closure { capture_clause, body: body_id, .. } => {
let body = self.fcx.tcx.hir().body(body_id);
self.visit_body(body);
self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
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);

View File

@ -262,7 +262,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
self.fix_index_builtin_expr(e);
match e.kind {
hir::ExprKind::Closure(_, _, body, _, _) => {
hir::ExprKind::Closure { body, .. } => {
let body = self.fcx.tcx.hir().body(body);
for param in body.params {
self.visit_node_id(e.span, param.hir_id);

View File

@ -295,7 +295,7 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Closure(..) = expr.kind {
if let hir::ExprKind::Closure { .. } = expr.kind {
let def_id = self.tcx.hir().local_def_id(expr.hir_id);
self.tcx.ensure().generics_of(def_id);
// We do not call `type_of` for closures here as that
@ -1567,7 +1567,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
}
}
}
Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
Some(tcx.typeck_root_def_id(def_id))
}
Node::Item(item) => match item.kind {
@ -1718,7 +1718,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
// provide junk type parameter defs - the only place that
// cares about anything but the length is instantiation,
// and we don't do that for closures.
if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) = node {
if let Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { movability: gen, .. }, .. }) =
node
{
let dummy_args = if gen.is_some() {
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
} else {
@ -1881,7 +1883,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
))
}
Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
// Closure signatures are not like other function
// signatures and cannot be accessed through `fn_sig`. For
// example, a closure signature excludes the `self`
@ -2567,9 +2569,9 @@ fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::GeneratorKind> {
match tcx.hir().get_if_local(def_id) {
Some(Node::Expr(&rustc_hir::Expr {
kind: rustc_hir::ExprKind::Closure(_, _, body_id, _, _),
kind: rustc_hir::ExprKind::Closure { body, .. },
..
})) => tcx.hir().body(body_id).generator_kind(),
})) => tcx.hir().body(body).generator_kind(),
Some(_) => None,
_ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
}

View File

@ -405,7 +405,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
Node::Field(field) => icx.to_ty(field.ty),
Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => tcx.typeck(def_id).node_type(hir_id),
Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id),
Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
// We defer to `type_of` of the corresponding parameter
@ -593,7 +593,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
self.tcx.hir()
}
fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
if let hir::ExprKind::Closure(..) = ex.kind {
if let hir::ExprKind::Closure { .. } = ex.kind {
let def_id = self.tcx.hir().local_def_id(ex.hir_id);
self.check(def_id);
}

View File

@ -437,7 +437,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.consume_expr(base);
}
hir::ExprKind::Closure(..) => {
hir::ExprKind::Closure { .. } => {
self.walk_captures(expr);
}

View File

@ -359,7 +359,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::Call(..)
| hir::ExprKind::Assign(..)
| hir::ExprKind::AssignOp(..)
| hir::ExprKind::Closure(..)
| hir::ExprKind::Closure { .. }
| hir::ExprKind::Ret(..)
| hir::ExprKind::Unary(..)
| hir::ExprKind::Yield(..)

View File

@ -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() {

View File

@ -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;

View File

@ -498,7 +498,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(..)

View File

@ -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() {

View File

@ -158,8 +158,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);
}
}

View File

@ -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),

View File

@ -182,7 +182,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
.fold(NeverLoopResult::Otherwise, combine_both),
ExprKind::Struct(_, _, None)
| ExprKind::Yield(_, _)
| ExprKind::Closure(_, _, _, _, _)
| ExprKind::Closure { .. }
| ExprKind::Path(_)
| ExprKind::ConstBlock(_)
| ExprKind::Lit(_)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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(

View File

@ -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| ...`)",

View File

@ -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));
}

View File

@ -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));

View File

@ -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(_) |

View File

@ -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)

View File

@ -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;

View File

@ -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 {

View File

@ -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, "..");

View File

@ -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 {

View File

@ -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));

View File

@ -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)`

View File

@ -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) {

View File

@ -112,7 +112,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 {
@ -243,7 +243,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
@ -315,7 +315,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,

View File

@ -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();

View File

@ -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)),

View File

@ -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);

View File

@ -134,7 +134,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;

View File

@ -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 {

View File

@ -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 &[

View File

@ -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);
},

View File

@ -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(..)

View File

@ -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);

View File

@ -962,7 +962,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 {
@ -1200,7 +1200,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),
@ -1693,7 +1693,7 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t
_,
&[
Expr {
kind: ExprKind::Closure(_, _, body, _, _),
kind: ExprKind::Closure { body, .. },
..
},
],
@ -1780,7 +1780,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)),
}
}

View File

@ -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

View File

@ -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 { .. },
..
})
)