diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f87269960bc..c6d312c922c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3161,7 +3161,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> Option> { // Define a fallback for when we can't match a closure. let fallback = || { - let is_closure = self.infcx.tcx.is_closure_or_coroutine(self.mir_def_id().to_def_id()); + let is_closure = self.infcx.tcx.is_closure_like(self.mir_def_id().to_def_id()); if is_closure { None } else { @@ -3372,7 +3372,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { sig: ty::PolyFnSig<'tcx>, ) -> Option> { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); - let is_closure = self.infcx.tcx.is_closure_or_coroutine(did.to_def_id()); + let is_closure = self.infcx.tcx.is_closure_like(did.to_def_id()); let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did); let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 9e7fd45ec19..350645e0734 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { local, projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { - debug_assert!(is_closure_or_coroutine( + debug_assert!(is_closure_like( Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty )); @@ -126,9 +126,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { item_msg = access_place_desc; debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref()); - debug_assert!(is_closure_or_coroutine( - the_place_err.ty(self.body, self.infcx.tcx).ty - )); + debug_assert!(is_closure_like(the_place_err.ty(self.body, self.infcx.tcx).ty)); reason = if self.is_upvar_field_projection(access_place.as_ref()).is_some() { ", as it is a captured variable in a `Fn` closure".to_string() @@ -389,7 +387,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { local, projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { - debug_assert!(is_closure_or_coroutine( + debug_assert!(is_closure_like( Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty )); @@ -1474,7 +1472,8 @@ fn suggest_ampmut<'tcx>( } } -fn is_closure_or_coroutine(ty: Ty<'_>) -> bool { +/// If the type is a `Coroutine`, `Closure`, or `CoroutineClosure` +fn is_closure_like(ty: Ty<'_>) -> bool { ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() } diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index a5a7ce4ea3e..af5b635ae66 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -29,7 +29,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) { let mir_def_id = body.source.def_id().expect_local(); - if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) { + if !self.tcx().is_closure_like(mir_def_id.to_def_id()) { return; } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 07c83f1aa08..f9eaa0d94cb 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -479,7 +479,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( // `+multivalue` feature because the purpose of the wasm abi is to match // the WebAssembly specification, which has this feature. This won't be // needed when LLVM enables this `multivalue` feature by default. - if !cx.tcx.is_closure_or_coroutine(instance.def_id()) { + if !cx.tcx.is_closure_like(instance.def_id()) { let abi = cx.tcx.fn_sig(instance.def_id()).skip_binder().abi(); if abi == Abi::Wasm { function_features.push("+multivalue".to_string()); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index b387d0b2258..9e23757fcee 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -229,7 +229,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::track_caller => { - let is_closure = tcx.is_closure_or_coroutine(did.to_def_id()); + let is_closure = tcx.is_closure_like(did.to_def_id()); if !is_closure && let Some(fn_sig) = fn_sig() @@ -274,7 +274,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } sym::target_feature => { - if !tcx.is_closure_or_coroutine(did.to_def_id()) + if !tcx.is_closure_like(did.to_def_id()) && let Some(fn_sig) = fn_sig() && fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal { @@ -529,7 +529,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // would result in this closure being compiled without the inherited target features, but this // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute. if tcx.features().target_feature_11 - && tcx.is_closure_or_coroutine(did.to_def_id()) + && tcx.is_closure_like(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always { let owner_id = tcx.parent(did.to_def_id()); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 98276ff2e68..0eaeb8b8089 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -72,7 +72,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn fn_sig(&self) -> PolyFnSig<'tcx> { let did = self.def_id().to_def_id(); - if self.tcx.is_closure_or_coroutine(did) { + if self.tcx.is_closure_like(did) { let ty = self.tcx.type_of(did).instantiate_identity(); let ty::Closure(_, args) = ty.kind() else { bug!("type_of closure not ty::Closure") }; args.as_closure().sig() diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 81ec7ddb629..a0f7a30c2c3 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -115,6 +115,12 @@ pub enum DefKind { Impl { of_trait: bool, }, + /// A closure, coroutine, or coroutine-closure. + /// + /// These are all represented with the same `ExprKind::Closure` in the AST and HIR, + /// which makes it difficult to distinguish these during def collection. Therefore, + /// we treat them all the same, and code which needs to distinguish them can match + /// or `hir::ClosureKind` or `type_of`. Closure, } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index aab78465f8c..be68b598e76 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -90,8 +90,7 @@ pub(super) fn check_fn<'a, 'tcx>( // ty.span == binding_span iff this is a closure parameter with no type ascription, // or if it's an implicit `self` parameter traits::SizedArgumentType( - if ty_span == Some(param.span) && tcx.is_closure_or_coroutine(fn_def_id.into()) - { + if ty_span == Some(param.span) && tcx.is_closure_like(fn_def_id.into()) { None } else { ty.map(|ty| ty.hir_id) diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index f9af357f0e7..4d37f725c94 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { // ascription, or if it's an implicit `self` parameter traits::SizedArgumentType( if ty_span == ident.span - && self.fcx.tcx.is_closure_or_coroutine(self.fcx.body_id.into()) + && self.fcx.tcx.is_closure_like(self.fcx.body_id.into()) { None } else { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index b601b465668..a011f6114de 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -491,7 +491,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: let kind = tcx.def_kind(def_id); let is_function = match kind { DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, - _ => tcx.is_closure_or_coroutine(def_id), + _ => tcx.is_closure_like(def_id), }; match (kind, body.source.promoted) { (_, Some(i)) => write!(w, "{i:?} in ")?, diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 8ff5b135aca..7db64504f85 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -197,7 +197,7 @@ pub struct ClosureTypeInfo<'tcx> { } fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> { - debug_assert!(tcx.is_closure_or_coroutine(def.to_def_id())); + debug_assert!(tcx.is_closure_like(def.to_def_id())); let typeck_results = tcx.typeck(def); let user_provided_sig = typeck_results.user_provided_sigs[&def]; let captures = typeck_results.closure_min_captures_flattened(def); @@ -217,7 +217,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] { - if !self.is_closure_or_coroutine(def_id.to_def_id()) { + if !self.is_closure_like(def_id.to_def_id()) { return &[]; }; self.closure_typeinfo(def_id).captures diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 8848d216f5b..01b7be98b18 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -465,10 +465,7 @@ impl<'tcx> Instance<'tcx> { ) -> Option> { debug!("resolve(def_id={:?}, args={:?})", def_id, args); // Use either `resolve_closure` or `resolve_for_vtable` - assert!( - !tcx.is_closure_or_coroutine(def_id), - "Called `resolve_for_fn_ptr` on closure: {def_id:?}" - ); + assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}"); Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => { @@ -530,7 +527,7 @@ impl<'tcx> Instance<'tcx> { }) ) { - if tcx.is_closure_or_coroutine(def) { + if tcx.is_closure_like(def) { debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", def, def_id, args); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4feaeb0dd05..c674a868d9f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -541,13 +541,15 @@ impl<'tcx> TyCtxt<'tcx> { Ok(()) } - /// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note - /// that closures have a `DefId`, but the closure *expression* also - /// has a `HirId` that is located within the context where the - /// closure appears (and, sadly, a corresponding `NodeId`, since - /// those are not yet phased out). The parent of the closure's - /// `DefId` will also be the context where it appears. - pub fn is_closure_or_coroutine(self, def_id: DefId) -> bool { + /// Returns `true` if `def_id` refers to a closure, coroutine, or coroutine-closure + /// (i.e. an async closure). These are all represented by `hir::Closure`, and all + /// have the same `DefKind`. + /// + /// Note that closures have a `DefId`, but the closure *expression* also has a + // `HirId` that is located within the context where the closure appears (and, sadly, + // a corresponding `NodeId`, since those are not yet phased out). The parent of + // the closure's `DefId` will also be the context where it appears. + pub fn is_closure_like(self, def_id: DefId) -> bool { matches!(self.def_kind(def_id), DefKind::Closure) } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 01fae7c0bec..4ac8dde03a6 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -138,7 +138,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( let (span, visible_macro) = unexpand_into_body_span_with_visible_macro(expn_span, body_span)?; - Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_or_coroutine(statement))) + Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement))) }); let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| { @@ -153,7 +153,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( }) } -fn is_closure_or_coroutine(statement: &Statement<'_>) -> bool { +fn is_closure_like(statement: &Statement<'_>) -> bool { match statement.kind { StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind { AggregateKind::Closure(_, _) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3376af98653..a771fa86eb7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1154,7 +1154,7 @@ fn create_fn_mono_item<'tcx>( let def_id = instance.def_id(); if tcx.sess.opts.unstable_opts.profile_closures && def_id.is_local() - && tcx.is_closure_or_coroutine(def_id) + && tcx.is_closure_like(def_id) { crate::util::dump_closure_profile(tcx, instance); } diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index ded20c38543..4d44e8762b0 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -11,7 +11,7 @@ use rustc_span::Span; pub fn provide(providers: &mut Providers) { providers.upvars_mentioned = |tcx, def_id| { - if !tcx.is_closure_or_coroutine(def_id) { + if !tcx.is_closure_like(def_id) { return None; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index 700a5dd4a85..6528a7b369f 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { fn is_by_value_closure_capture(cx: &LateContext<'_>, redefinition: HirId, root_variable: HirId) -> bool { let closure_def_id = cx.tcx.hir().enclosing_body_owner(redefinition); - cx.tcx.is_closure_or_coroutine(closure_def_id.to_def_id()) + cx.tcx.is_closure_like(closure_def_id.to_def_id()) && cx.tcx.closure_captures(closure_def_id).iter().any(|c| { matches!(c.info.capture_kind, UpvarCapture::ByValue) && matches!(c.place.base, PlaceBase::Upvar(upvar) if upvar.var_path.hir_id == root_variable)