From efa2fffd3a5ce007bf8fc03d74fac3391b9489cd Mon Sep 17 00:00:00 2001 From: bohan Date: Tue, 28 Nov 2023 22:47:52 +0800 Subject: [PATCH 1/2] aligns the behavior to that prior to #118311 --- compiler/rustc_metadata/src/rmeta/encoder.rs | 13 +++++++------ compiler/rustc_middle/src/ty/mod.rs | 14 ++++++++++---- compiler/rustc_mir_build/src/build/mod.rs | 4 +++- .../rustc_mir_transform/src/cross_crate_inline.rs | 1 + compiler/rustc_mir_transform/src/lib.rs | 1 + 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 765bb7a362e5a..9fc323ca0aeba 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -862,7 +862,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { } } -fn should_encode_attrs(def_kind: DefKind) -> bool { +fn should_encode_attrs(def_kind: DefKind, is_coroutine: bool) -> bool { match def_kind { DefKind::Mod | DefKind::Struct @@ -886,7 +886,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { // closures from upstream crates, too. This is used by // https://github.com/model-checking/kani and is not a performance // or maintenance issue for us. - DefKind::Closure => true, + DefKind::Closure => !is_coroutine, DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(..) @@ -1228,11 +1228,11 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { } } -fn should_encode_constness(def_kind: DefKind) -> bool { +fn should_encode_constness(def_kind: DefKind, is_coroutine: bool) -> bool { match def_kind { + DefKind::Closure => !is_coroutine, DefKind::Fn | DefKind::AssocFn - | DefKind::Closure | DefKind::Impl { of_trait: true } | DefKind::Variant | DefKind::Ctor(..) => true, @@ -1345,12 +1345,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); + let is_coroutine = def_kind == DefKind::Closure && tcx.is_coroutine(def_id); self.tables.def_kind.set_some(def_id.index, def_kind); if should_encode_span(def_kind) { let def_span = tcx.def_span(local_id); record!(self.tables.def_span[def_id] <- def_span); } - if should_encode_attrs(def_kind) { + if should_encode_attrs(def_kind, is_coroutine) { self.encode_attrs(local_id); } if should_encode_expn_that_defined(def_kind) { @@ -1405,7 +1406,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir { record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); } - if should_encode_constness(def_kind) { + if should_encode_constness(def_kind, is_coroutine) { self.tables.constness.set_some(def_id.index, self.tcx.constness(def_id)); } if let DefKind::Fn | DefKind::AssocFn = def_kind { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 24cba913bb891..84aaf9b34d0ad 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2464,10 +2464,16 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn is_const_fn_raw(self, def_id: DefId) -> bool { - matches!( - self.def_kind(def_id), - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure - ) && self.constness(def_id) == hir::Constness::Const + let def_kind = self.def_kind(def_id); + if def_kind == DefKind::Closure + && !self.is_coroutine(def_id) + && self.constness(def_id) == hir::Constness::Const + { + true + } else { + matches!(def_kind, DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..)) + && self.constness(def_id) == hir::Constness::Const + } } #[inline] diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 19b6496b102ef..9040f89038e14 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -474,7 +474,9 @@ fn construct_fn<'tcx>( }; let mut abi = fn_sig.abi; - if let DefKind::Closure = tcx.def_kind(fn_def) { + if let DefKind::Closure = tcx.def_kind(fn_def) + && !tcx.is_coroutine(fn_def.to_def_id()) + { // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. abi = Abi::Rust; diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 261d9dd448d47..0468ec04799b6 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -32,6 +32,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { // This just reproduces the logic from Instance::requires_inline. match tcx.def_kind(def_id) { + DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => return false, DefKind::Ctor(..) | DefKind::Closure => return true, DefKind::Fn | DefKind::AssocFn => {} _ => return false, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index fff760ba399be..5e3ea7dbdf385 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -323,6 +323,7 @@ fn mir_promoted( // Also this means promotion can rely on all const checks having been done. let const_qualifs = match tcx.def_kind(def) { + DefKind::Closure if tcx.is_coroutine(def.to_def_id()) => ConstQualifs::default(), DefKind::Fn | DefKind::AssocFn | DefKind::Closure if tcx.constness(def) == hir::Constness::Const || tcx.is_const_default_method(def.to_def_id()) => From 77f9a77cb8cd4580a17d77e0bb8907474b9ac143 Mon Sep 17 00:00:00 2001 From: bohan Date: Wed, 29 Nov 2023 23:59:57 +0800 Subject: [PATCH 2/2] use `closure.movability` to judge coroutine --- .../src/diagnostics/conflict_errors.rs | 10 +++------- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +--- compiler/rustc_hir_analysis/src/check/check.rs | 4 ++-- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 8 ++++---- compiler/rustc_middle/src/ty/context.rs | 14 ++++++++++++-- compiler/rustc_middle/src/ty/mod.rs | 14 ++++---------- compiler/rustc_mir_build/src/build/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 4 ++-- compiler/rustc_mir_transform/src/const_prop.rs | 2 +- .../rustc_mir_transform/src/const_prop_lint.rs | 2 +- .../rustc_mir_transform/src/cross_crate_inline.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 4 ++-- 13 files changed, 35 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index ef4bf54345436..51cfc2ed330d2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2071,13 +2071,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .opt_item_name(self.mir_def_id().to_def_id()) .map(|name| format!("function `{name}`")) .unwrap_or_else(|| { - match &self.infcx.tcx.def_kind(self.mir_def_id()) { - DefKind::Closure - if self - .infcx - .tcx - .is_coroutine(self.mir_def_id().to_def_id()) => - { + let def_id = self.mir_def_id(); + match &self.infcx.tcx.def_kind(def_id) { + DefKind::Closure if self.infcx.tcx.is_coroutine(def_id) => { "enclosing coroutine" } DefKind::Closure => "enclosing closure", diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d4fd1a3cf2ae5..abb431c151d9e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2678,9 +2678,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let parent_args = match tcx.def_kind(def_id) { - DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => { - args.as_coroutine().parent_args() - } + DefKind::Closure if tcx.is_coroutine(def_id) => args.as_coroutine().parent_args(), DefKind::Closure => args.as_closure().parent_args(), DefKind::InlineConst => args.as_inline_const().parent_args(), other => bug!("unexpected item {:?}", other), diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index fbed6f33e5928..bf282e83a5bd0 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1449,7 +1449,7 @@ fn opaque_type_cycle_error( label_match(capture.place.ty(), capture.get_path_span(tcx)); } // Label any coroutine locals that capture the opaque - if tcx.is_coroutine(closure_def_id) + if tcx.is_coroutine(closure_local_did) && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id) { for interior_ty in &coroutine_layout.field_tys { @@ -1470,7 +1470,7 @@ pub(super) fn check_coroutine_obligations( tcx: TyCtxt<'_>, def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { - debug_assert!(tcx.is_coroutine(def_id.to_def_id())); + debug_assert!(tcx.is_coroutine(def_id)); let typeck = tcx.typeck(def_id); let param_env = tcx.param_env(def_id); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 88212d164bc04..bfa5a18e3c1ee 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -757,7 +757,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); tcx.hir().par_body_owners(|def_id| { - if tcx.is_coroutine(def_id.to_def_id()) { + if tcx.is_coroutine(def_id) { tcx.ensure().mir_coroutine_witnesses(def_id); tcx.ensure().check_coroutine_obligations(def_id); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 9fc323ca0aeba..14f712dae3c4a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1045,7 +1045,7 @@ fn should_encode_mir( | DefKind::Static(..) | DefKind::Const => (true, false), // Coroutines require optimized MIR to compute layout. - DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true), + DefKind::Closure if tcx.is_coroutine(def_id) => (false, true), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { let generics = tcx.generics_of(def_id); @@ -1345,7 +1345,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); - let is_coroutine = def_kind == DefKind::Closure && tcx.is_coroutine(def_id); + let is_coroutine = def_kind == DefKind::Closure && tcx.is_coroutine(local_id); self.tables.def_kind.set_some(def_id.index, def_kind); if should_encode_span(def_kind) { let def_span = tcx.def_span(local_id); @@ -1627,7 +1627,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); - if self.tcx.is_coroutine(def_id.to_def_id()) + if self.tcx.is_coroutine(def_id) && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id) { record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); @@ -1654,7 +1654,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); - if self.tcx.is_coroutine(def_id.to_def_id()) + if self.tcx.is_coroutine(def_id) && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id) { record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bb02c6e0c7856..a8346151644f4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -807,8 +807,18 @@ impl<'tcx> TyCtxt<'tcx> { self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did) } - pub fn is_coroutine(self, def_id: DefId) -> bool { - self.coroutine_kind(def_id).is_some() + pub fn is_coroutine(self, def_id: LocalDefId) -> bool { + let hir_id = self.local_def_id_to_hir_id(def_id); + let Some(node) = self.hir().find(hir_id) else { + return false; + }; + if let hir::Node::Expr(expr) = node + && let hir::ExprKind::Closure(closure) = expr.kind + { + closure.movability.is_some() + } else { + false + } } /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 84aaf9b34d0ad..24cba913bb891 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2464,16 +2464,10 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn is_const_fn_raw(self, def_id: DefId) -> bool { - let def_kind = self.def_kind(def_id); - if def_kind == DefKind::Closure - && !self.is_coroutine(def_id) - && self.constness(def_id) == hir::Constness::Const - { - true - } else { - matches!(def_kind, DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..)) - && self.constness(def_id) == hir::Constness::Const - } + matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure + ) && self.constness(def_id) == hir::Constness::Const } #[inline] diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9040f89038e14..430d8527f961d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -475,7 +475,7 @@ fn construct_fn<'tcx>( let mut abi = fn_sig.abi; if let DefKind::Closure = tcx.def_kind(fn_def) - && !tcx.is_coroutine(fn_def.to_def_id()) + && !tcx.is_coroutine(fn_def) { // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 4eba7103c0cda..eab6b59400334 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -37,7 +37,7 @@ pub(crate) fn thir_body( // The resume argument may be missing, in that case we need to provide it here. // It will always be `()` in this case. - if tcx.is_coroutine(owner_def.to_def_id()) && body.params.is_empty() { + if tcx.is_coroutine(owner_def) && body.params.is_empty() { cx.thir.params.push(Param { ty: Ty::new_unit(tcx), pat: None, @@ -119,7 +119,7 @@ impl<'tcx> Cx<'tcx> { fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option> { match self.tcx.def_kind(owner_def) { - DefKind::Closure if self.tcx.is_coroutine(owner_def.to_def_id()) => { + DefKind::Closure if self.tcx.is_coroutine(owner_def) => { let coroutine_ty = self.typeck_results.node_type(owner_id); let coroutine_param = Param { ty: coroutine_ty, diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index b96125de95e7a..a165e6380c577 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -84,7 +84,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles // computing their layout. - if tcx.is_coroutine(def_id.to_def_id()) { + if def_kind == DefKind::Closure && tcx.is_coroutine(def_id) { trace!("ConstProp skipped for coroutine {:?}", def_id); return; } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 99eecb567f277..fb5777ceb8e1d 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -61,7 +61,7 @@ impl<'tcx> MirLint<'tcx> for ConstPropLint { // FIXME(welseywiser) const prop doesn't work on coroutines because of query cycles // computing their layout. - if tcx.is_coroutine(def_id.to_def_id()) { + if def_kind == DefKind::Closure && tcx.is_coroutine(def_id) { trace!("ConstPropLint skipped for coroutine {:?}", def_id); return; } diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 0468ec04799b6..174137dfafa48 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -32,7 +32,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { // This just reproduces the logic from Instance::requires_inline. match tcx.def_kind(def_id) { - DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => return false, + DefKind::Closure if tcx.is_coroutine(def_id) => return false, DefKind::Ctor(..) | DefKind::Closure => return true, DefKind::Fn | DefKind::AssocFn => {} _ => return false, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 5e3ea7dbdf385..7c3066c0fb599 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -323,7 +323,7 @@ fn mir_promoted( // Also this means promotion can rely on all const checks having been done. let const_qualifs = match tcx.def_kind(def) { - DefKind::Closure if tcx.is_coroutine(def.to_def_id()) => ConstQualifs::default(), + DefKind::Closure if tcx.is_coroutine(def) => ConstQualifs::default(), DefKind::Fn | DefKind::AssocFn | DefKind::Closure if tcx.constness(def) == hir::Constness::Const || tcx.is_const_default_method(def.to_def_id()) => @@ -396,7 +396,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't /// end up missing the source MIR due to stealing happening. fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { - if tcx.is_coroutine(def.to_def_id()) { + if tcx.is_coroutine(def) { tcx.ensure_with_value().mir_coroutine_witnesses(def); } let mir_borrowck = tcx.mir_borrowck(def);