From 24a24ec6ba24bfe5e0980d22f585c98a608ec701 Mon Sep 17 00:00:00 2001 From: zetanumbers Date: Tue, 13 Feb 2024 12:31:41 +0300 Subject: Add simple async drop glue generation Explainer: https://zetanumbers.github.io/book/async-drop-design.html https://github.com/rust-lang/rust/pull/121801 --- .../rustc_codegen_ssa/src/back/symbol_export.rs | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index b19f52182b6..008543e4470 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -363,6 +363,24 @@ fn exported_symbols_provider_local( }, )); } + MonoItem::Fn(Instance { + def: InstanceDef::AsyncDropGlueCtorShim(def_id, ty), + args, + }) => { + // A little sanity-check + debug_assert_eq!( + args.non_erasable_generics(tcx, def_id).skip(1).next(), + Some(GenericArgKind::Type(ty)) + ); + symbols.push(( + ExportedSymbol::AsyncDropGlueCtorShim(ty), + SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + }, + )); + } _ => { // Any other symbols don't qualify for sharing } @@ -385,6 +403,7 @@ fn upstream_monomorphizations_provider( let mut instances: DefIdMap> = Default::default(); let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn(); + let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn(); for &cnum in cnums.iter() { for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() { @@ -399,6 +418,18 @@ fn upstream_monomorphizations_provider( continue; } } + ExportedSymbol::AsyncDropGlueCtorShim(ty) => { + if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id { + ( + async_drop_in_place_fn_def_id, + tcx.mk_args(&[tcx.lifetimes.re_erased.into(), ty.into()]), + ) + } else { + // `drop_in_place` in place does not exist, don't try + // to use it. + continue; + } + } ExportedSymbol::NonGeneric(..) | ExportedSymbol::ThreadLocalShim(..) | ExportedSymbol::NoDefId(..) => { @@ -534,6 +565,13 @@ pub fn symbol_name_for_instance_in_crate<'tcx>( Instance::resolve_drop_in_place(tcx, ty), instantiating_crate, ), + ExportedSymbol::AsyncDropGlueCtorShim(ty) => { + rustc_symbol_mangling::symbol_name_for_instance_in_crate( + tcx, + Instance::resolve_async_drop_in_place(tcx, ty), + instantiating_crate, + ) + } ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(), } } @@ -582,6 +620,9 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( // DropGlue always use the Rust calling convention and thus follow the target's default // symbol decoration scheme. ExportedSymbol::DropGlue(..) => None, + // AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the + // target's default symbol decoration scheme. + ExportedSymbol::AsyncDropGlueCtorShim(..) => None, // NoDefId always follow the target's default symbol decoration scheme. ExportedSymbol::NoDefId(..) => None, // ThreadLocalShim always follow the target's default symbol decoration scheme. -- cgit 1.4.1-3-g733a5 From 80c0b7e90fd064ea6c5fe8594b301e0fcc55af68 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Wed, 17 Apr 2024 20:49:53 +0300 Subject: Use non-exhaustive matches for TyKind Also no longer export noop async_drop_in_place_raw --- .../rustc_codegen_ssa/src/back/symbol_export.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 3 +- compiler/rustc_middle/src/ty/instance.rs | 5 +- compiler/rustc_middle/src/ty/sty.rs | 43 +++----- compiler/rustc_middle/src/ty/util.rs | 117 +++++++++++---------- compiler/rustc_mir_transform/src/inline.rs | 4 +- .../src/shim/async_destructor_ctor.rs | 80 +++++++------- compiler/rustc_monomorphize/src/collector.rs | 4 +- compiler/rustc_monomorphize/src/partitioning.rs | 3 +- .../src/solve/normalizes_to/mod.rs | 12 +-- .../rustc_trait_selection/src/traits/project.rs | 4 +- compiler/rustc_ty_utils/src/instance.rs | 53 +++------- 13 files changed, 150 insertions(+), 182 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 008543e4470..cce3f0e6f2d 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -364,7 +364,7 @@ fn exported_symbols_provider_local( )); } MonoItem::Fn(Instance { - def: InstanceDef::AsyncDropGlueCtorShim(def_id, ty), + def: InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)), args, }) => { // A little sanity-check diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index d81a9772a09..151170d78f4 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -187,7 +187,7 @@ fn dump_path<'tcx>( })); s } - ty::InstanceDef::AsyncDropGlueCtorShim(_, ty) => { + ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => { // Unfortunately, pretty-printed typed are not very filename-friendly. // We dome some filtering. let mut s = ".".to_owned(); diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 01bd10c2007..1c38a69c7ec 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -350,13 +350,14 @@ macro_rules! make_mir_visitor { receiver_by_ref: _, } | ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id } | + ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, None) | ty::InstanceDef::DropGlue(_def_id, None) => {} ty::InstanceDef::FnPtrShim(_def_id, ty) | ty::InstanceDef::DropGlue(_def_id, Some(ty)) | ty::InstanceDef::CloneShim(_def_id, ty) | ty::InstanceDef::FnPtrAddrShim(_def_id, ty) | - ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, ty) => { + ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, Some(ty)) => { // FIXME(eddyb) use a better `TyContext` here. self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 904f1aff94b..c7c4225c80e 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -173,7 +173,7 @@ pub enum InstanceDef<'tcx> { /// /// The `DefId` is for `core::future::async_drop::async_drop_in_place`, the `Ty` /// is the type `T`. - AsyncDropGlueCtorShim(DefId, Ty<'tcx>), + AsyncDropGlueCtorShim(DefId, Option>), } impl<'tcx> Instance<'tcx> { @@ -406,7 +406,8 @@ fn fmt_instance( InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"), - InstanceDef::AsyncDropGlueCtorShim(_, ty) => write!(f, " - shim({ty})"), + InstanceDef::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"), + InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 135ade6d684..2a2781655c4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2319,6 +2319,10 @@ impl<'tcx> Ty<'tcx> { /// Returns the type of the async destructor of this type. pub fn async_destructor_ty(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Ty<'tcx> { + if self.is_async_destructor_noop(tcx, param_env) || matches!(self.kind(), ty::Error(_)) { + return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop) + .instantiate_identity(); + } match *self.kind() { ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { let assoc_items = tcx @@ -2333,9 +2337,6 @@ impl<'tcx> Ty<'tcx> { .instantiate(tcx, &[dtor.into()]) } - ty::Adt(adt_def, _) if adt_def.is_manually_drop() => { - Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop).instantiate_identity() - } ty::Adt(adt_def, args) if adt_def.is_enum() || adt_def.is_struct() => self .adt_async_destructor_ty( tcx, @@ -2357,34 +2358,10 @@ impl<'tcx> Ty<'tcx> { ty::Adt(adt_def, _) => { assert!(adt_def.is_union()); - match self.surface_async_dropper_ty(tcx, param_env) { - None => Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop) - .instantiate_identity(), - Some(surface_drop) => { - Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse) - .instantiate(tcx, &[surface_drop.into()]) - } - } - } - - ty::Never - | ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::RawPtr(_, _) - | ty::Ref(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Error(_) => { - Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop).instantiate_identity() - } + let surface_drop = self.surface_async_dropper_ty(tcx, param_env).unwrap(); - ty::Dynamic(..) | ty::CoroutineWitness(..) | ty::Coroutine(..) | ty::Pat(..) => { - bug!("`async_destructor_ty` is not yet implemented for type: {self:?}") + Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse) + .instantiate(tcx, &[surface_drop.into()]) } ty::Bound(..) @@ -2393,6 +2370,8 @@ impl<'tcx> Ty<'tcx> { | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("`async_destructor_ty` applied to unexpected type: {self:?}") } + + _ => bug!("`async_destructor_ty` is not yet implemented for type: {self:?}"), } } @@ -2406,6 +2385,8 @@ impl<'tcx> Ty<'tcx> { I: Iterator + ExactSizeIterator, I::Item: IntoIterator>, { + debug_assert!(!self.is_async_destructor_noop(tcx, param_env)); + let defer = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropDefer); let chain = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain); @@ -2425,7 +2406,7 @@ impl<'tcx> Ty<'tcx> { .reduce(|other, matched| { either.instantiate(tcx, &[other.into(), matched.into(), self.into()]) }) - .unwrap_or(noop); + .unwrap(); let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx, param_env) { Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 1c3e8ffc13e..cd9d17cf930 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1306,8 +1306,7 @@ impl<'tcx> Ty<'tcx> { /// Checks whether values of this type `T` implements the `AsyncDrop` /// trait. pub fn has_surface_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.trivially_has_surface_async_drop() - && tcx.has_surface_async_drop_raw(param_env.and(self)) + self.could_have_surface_async_drop() && tcx.has_surface_async_drop_raw(param_env.and(self)) } /// Fast path helper for testing if a type has `AsyncDrop` @@ -1316,52 +1315,68 @@ impl<'tcx> Ty<'tcx> { /// Returning `false` means the type is known to not have `AsyncDrop` /// implementation. Returning `true` means nothing -- could be /// `AsyncDrop`, might not be. - fn trivially_has_surface_async_drop(self) -> bool { - match self.kind() { - ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Bool - | ty::Char - | ty::Str - | ty::Never - | ty::Ref(..) - | ty::RawPtr(_, _) - | ty::FnDef(..) - | ty::FnPtr(_) - | ty::Error(_) - | ty::Tuple(_) - | ty::Slice(_) - | ty::Array(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Pat(..) => false, - ty::Adt(..) - | ty::Bound(..) - | ty::Dynamic(..) - | ty::Foreign(_) - | ty::Infer(_) - | ty::Alias(..) - | ty::Param(_) - | ty::Placeholder(_) => true, - } + fn could_have_surface_async_drop(self) -> bool { + !self.is_async_destructor_trivially_noop() + && !matches!( + self.kind(), + ty::Tuple(_) + | ty::Slice(_) + | ty::Array(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + ) } /// Checks whether values of this type `T` implements the `AsyncDrop` /// trait. pub fn has_surface_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.trivially_has_surface_drop() && tcx.has_surface_drop_raw(param_env.and(self)) + self.could_have_surface_drop() && tcx.has_surface_drop_raw(param_env.and(self)) } - /// Fast path helper for testing if a type has `AsyncDrop` - /// implementation. + /// Fast path helper for testing if a type has `Drop` implementation. /// - /// Returning `false` means the type is known to not have `AsyncDrop` + /// Returning `false` means the type is known to not have `Drop` /// implementation. Returning `true` means nothing -- could be - /// `AsyncDrop`, might not be. - fn trivially_has_surface_drop(self) -> bool { + /// `Drop`, might not be. + fn could_have_surface_drop(self) -> bool { + self.is_async_destructor_trivially_noop() + && !matches!( + self.kind(), + ty::Tuple(_) + | ty::Slice(_) + | ty::Array(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + ) + } + + /// Checks whether values of this type `T` implement has noop async destructor. + // + // FIXME: implement optimization to make ADTs, which do not need drop, + // to skip fields or to have noop async destructor. + pub fn is_async_destructor_noop( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + self.is_async_destructor_trivially_noop() + || if let ty::Adt(adt_def, _) = self.kind() { + (adt_def.is_union() || adt_def.is_payloadfree()) + && !self.has_surface_async_drop(tcx, param_env) + && !self.has_surface_drop(tcx, param_env) + } else { + false + } + } + + /// Fast path helper for testing if a type has noop async destructor. + /// + /// Returning `true` means the type is known to have noop async destructor + /// implementation. Returning `true` means nothing -- could be + /// `Drop`, might not be. + fn is_async_destructor_trivially_noop(self) -> bool { match self.kind() { ty::Int(_) | ty::Uint(_) @@ -1371,26 +1386,12 @@ impl<'tcx> Ty<'tcx> { | ty::Str | ty::Never | ty::Ref(..) - | ty::RawPtr(_, _) + | ty::RawPtr(..) | ty::FnDef(..) - | ty::FnPtr(_) - | ty::Error(_) - | ty::Tuple(_) - | ty::Slice(_) - | ty::Array(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Pat(..) => false, - ty::Adt(..) - | ty::Bound(..) - | ty::Dynamic(..) - | ty::Foreign(_) - | ty::Infer(_) - | ty::Alias(..) - | ty::Param(_) - | ty::Placeholder(_) => true, + | ty::FnPtr(_) => true, + ty::Tuple(tys) => tys.is_empty(), + ty::Adt(adt_def, _) => adt_def.is_manually_drop(), + _ => false, } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 365e3dc36d4..1af03a5afe5 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1072,8 +1072,8 @@ fn try_instance_mir<'tcx>( tcx: TyCtxt<'tcx>, instance: InstanceDef<'tcx>, ) -> Result<&'tcx Body<'tcx>, &'static str> { - if let ty::InstanceDef::DropGlue(_, Some(ty)) | ty::InstanceDef::AsyncDropGlueCtorShim(_, ty) = - instance + if let ty::InstanceDef::DropGlue(_, Some(ty)) + | ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) = instance && let ty::Adt(def, args) = ty.kind() { let fields = def.all_fields(); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 095f41fb3d8..a423e324781 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -24,9 +24,11 @@ use super::{local_decls_for_sig, new_body}; pub fn build_async_destructor_ctor_shim<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, - self_ty: Ty<'tcx>, + ty: Option>, ) -> Body<'tcx> { - AsyncDestructorCtorShimBuilder::new(tcx, def_id, self_ty).build() + debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); + + AsyncDestructorCtorShimBuilder::new(tcx, def_id, ty).build() } /// Builder for async_drop_in_place shim. Functions as a stack machine @@ -40,7 +42,7 @@ pub fn build_async_destructor_ctor_shim<'tcx>( struct AsyncDestructorCtorShimBuilder<'tcx> { tcx: TyCtxt<'tcx>, def_id: DefId, - self_ty: Ty<'tcx>, + self_ty: Option>, span: Span, source_info: SourceInfo, param_env: ty::ParamEnv<'tcx>, @@ -64,12 +66,12 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { const INPUT_COUNT: usize = 1; const MAX_STACK_LEN: usize = 2; - fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self { + fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Option>) -> Self { + // Assuming `async_drop_in_place::<()>` is the same as for any type with noop async destructor + let arg_ty = if let Some(ty) = self_ty { ty } else { tcx.types.unit }; + let sig = tcx.fn_sig(def_id).instantiate(tcx, &[arg_ty.into()]); + let sig = tcx.instantiate_bound_regions_with_erased(sig); let span = tcx.def_span(def_id); - let Some(sig) = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).no_bound_vars() - else { - span_bug!(span, "async_drop_in_place_raw with bound vars for `{self_ty}`"); - }; let source_info = SourceInfo::outermost(span); @@ -110,7 +112,9 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { } fn build(self) -> Body<'tcx> { - let (tcx, def_id, self_ty) = (self.tcx, self.def_id, self.self_ty); + let (tcx, def_id, Some(self_ty)) = (self.tcx, self.def_id, self.self_ty) else { + return self.build_noop(); + }; let surface_drop_kind = || { let param_env = tcx.param_env_reveal_all_normalized(def_id); @@ -127,8 +131,6 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { ty::Array(elem_ty, _) => self.build_slice(true, *elem_ty), ty::Slice(elem_ty) => self.build_slice(false, *elem_ty), - ty::Adt(adt_def, _) if adt_def.is_manually_drop() => self.build_noop(), - ty::Tuple(elem_tys) => self.build_chain(None, elem_tys.iter()), ty::Adt(adt_def, args) if adt_def.is_struct() => { let field_tys = adt_def.non_enum_variant().fields.iter().map(|f| f.ty(tcx, args)); @@ -143,35 +145,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { self.build_enum(*adt_def, *args, surface_drop_kind()) } - ty::Never - | ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(_) - | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Error(_) => self.build_noop(), - ty::Adt(adt_def, _) => { assert!(adt_def.is_union()); - match surface_drop_kind() { - Some(SurfaceDropKind::Async) => self.build_fused_async_surface(), - Some(SurfaceDropKind::Sync) => self.build_fused_sync_surface(), - None => self.build_noop(), + match surface_drop_kind().unwrap() { + SurfaceDropKind::Async => self.build_fused_async_surface(), + SurfaceDropKind::Sync => self.build_fused_sync_surface(), } } - ty::Dynamic(..) | ty::CoroutineWitness(..) | ty::Coroutine(..) | ty::Pat(..) => { - bug!( - "Building async destructor constructor shim is not yet implemented for type: {self_ty:?}" - ) - } - ty::Bound(..) | ty::Foreign(_) | ty::Placeholder(_) @@ -180,6 +161,12 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { | ty::Alias(..) => { bug!("Building async destructor for unexpected type: {self_ty:?}") } + + _ => { + bug!( + "Building async destructor constructor shim is not yet implemented for type: {self_ty:?}" + ) + } } } @@ -430,11 +417,15 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { } fn combine_async_surface(&mut self) -> Ty<'tcx> { - self.apply_combinator(1, LangItem::SurfaceAsyncDropInPlace, &[self.self_ty.into()]) + self.apply_combinator(1, LangItem::SurfaceAsyncDropInPlace, &[self.self_ty.unwrap().into()]) } fn combine_sync_surface(&mut self) -> Ty<'tcx> { - self.apply_combinator(1, LangItem::AsyncDropSurfaceDropInPlace, &[self.self_ty.into()]) + self.apply_combinator( + 1, + LangItem::AsyncDropSurfaceDropInPlace, + &[self.self_ty.unwrap().into()], + ) } fn combine_fuse(&mut self, inner_future_ty: Ty<'tcx>) -> Ty<'tcx> { @@ -457,7 +448,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { self.apply_combinator( 4, LangItem::AsyncDropEither, - &[other.into(), matched.into(), self.self_ty.into()], + &[other.into(), matched.into(), self.self_ty.unwrap().into()], ) } @@ -477,7 +468,18 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { debug_assert_eq!( output.ty(&self.locals, self.tcx), - self.self_ty.async_destructor_ty(self.tcx, self.param_env), + self.self_ty.map(|ty| ty.async_destructor_ty(self.tcx, self.param_env)).unwrap_or_else( + || { + self.tcx + .fn_sig( + self.tcx.require_lang_item(LangItem::AsyncDropNoop, Some(self.span)), + ) + .instantiate_identity() + .output() + .no_bound_vars() + .unwrap() + } + ), ); let dead_storage = match &output { Operand::Move(place) => Some(Statement { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5cbf13bd9ce..a8fa6fe002d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -966,14 +966,14 @@ fn visit_instance_use<'tcx>( ty::InstanceDef::ThreadLocalShim(..) => { bug!("{:?} being reified", instance); } - ty::InstanceDef::DropGlue(_, None) => { + ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => { // Don't need to emit noop drop glue if we are calling directly. if !is_direct_call { output.push(create_fn_mono_item(tcx, instance, source)); } } ty::InstanceDef::DropGlue(_, Some(_)) - | ty::InstanceDef::AsyncDropGlueCtorShim(..) + | ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) | ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 74098dccfcb..23e07890bb6 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -772,7 +772,7 @@ fn mono_item_visibility<'tcx>( let def_id = match instance.def { InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) - | InstanceDef::AsyncDropGlueCtorShim(def_id, _) => def_id, + | InstanceDef::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id, // We match the visibility of statics here InstanceDef::ThreadLocalShim(def_id) => { @@ -789,6 +789,7 @@ fn mono_item_visibility<'tcx>( | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) + | InstanceDef::AsyncDropGlueCtorShim(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, }; diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 6a2e58bc922..e4d961a7f0c 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -819,7 +819,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let self_ty = goal.predicate.self_ty(); - let discriminant_ty = match *self_ty.kind() { + let async_destructor_ty = match *self_ty.kind() { ty::Bool | ty::Char | ty::Int(..) @@ -833,14 +833,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Pat(..) | ty::Never | ty::Adt(_, _) | ty::Str | ty::Slice(_) - | ty::Dynamic(_, _, _) | ty::Tuple(_) | ty::Error(_) => self_ty.async_destructor_ty(ecx.tcx(), goal.param_env), @@ -858,10 +854,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { "unexpected self ty `{:?}` when normalizing `::AsyncDestructor`", goal.predicate.self_ty() ), + + _ => bug!( + "`consider_builtin_async_destruct_candidate` is not yet implemented for type: {self_ty:?}" + ), }; ecx.probe_misc_candidate("builtin async destruct").enter(|ecx| { - ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into()) + ecx.eq(goal.param_env, goal.predicate.term, async_destructor_ty.into()) .expect("expected goal term to be fully unconstrained"); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9217bf77ba6..47df11ff7f8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1100,14 +1100,14 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, // type parameters, opaques, and unnormalized projections don't have - // a known discriminant and may need to be normalized further or rely + // a known async destructor and may need to be normalized further or rely // on param env for async destructor projections ty::Param(_) | ty::Foreign(_) | ty::Alias(..) | ty::Bound(..) | ty::Placeholder(..) - | ty::Infer(..) + | ty::Infer(_) | ty::Error(_) => false, } } else if lang_items.pointee_trait() == Some(trait_ref.def_id) { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 3a18f4d0939..400556a7d6a 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -57,44 +57,25 @@ fn resolve_instance<'tcx>( } else if Some(def_id) == tcx.lang_items().async_drop_in_place_fn() { let ty = args.type_at(0); - match *ty.kind() { - ty::Array(..) - | ty::Slice(_) - | ty::Tuple(_) - | ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::RawPtr(_, _) - | ty::Ref(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Adt(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::CoroutineWitness(..) - | ty::Pat(..) - | ty::Never - | ty::Coroutine(..) => {} - - ty::Param(_) - | ty::Error(_) - | ty::Dynamic(..) - | ty::Alias(..) - | ty::Infer(ty::TyVar(_)) - | ty::Bound(..) - | ty::Foreign(_) - | ty::Placeholder(_) - | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - return Ok(None); + if ty.is_async_destructor_noop(tcx, param_env) { + match *ty.kind() { + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::Tuple(..) + | ty::Adt(..) + | ty::Dynamic(..) + | ty::Array(..) + | ty::Slice(..) => {} + // Async destructor ctor shims can only be built from ADTs. + _ => return Ok(None), } + debug!(" => nontrivial async drop glue ctor"); + ty::InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)) + } else { + debug!(" => trivial async drop glue ctor"); + ty::InstanceDef::AsyncDropGlueCtorShim(def_id, None) } - - debug!(" => async drop glue ctor"); - ty::InstanceDef::AsyncDropGlueCtorShim(def_id, ty) } else { debug!(" => free item"); // FIXME(effects): we may want to erase the effect param if that is present on this item. -- cgit 1.4.1-3-g733a5 From e239e73a77cda38b53e9a7716e01f0c2af995ff5 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Thu, 18 Apr 2024 15:18:30 +0300 Subject: Fix disabling the export of noop async_drop_in_place_raw --- compiler/rustc_codegen_ssa/src/mir/block.rs | 5 +- compiler/rustc_middle/src/mir/mono.rs | 4 +- compiler/rustc_middle/src/ty/instance.rs | 4 +- compiler/rustc_middle/src/ty/util.rs | 2 +- .../src/shim/async_destructor_ctor.rs | 54 ++++++++++++---------- compiler/rustc_smir/src/rustc_smir/context.rs | 6 +++ compiler/rustc_ty_utils/src/instance.rs | 2 +- compiler/stable_mir/src/compiler_interface.rs | 3 ++ compiler/stable_mir/src/mir/mono.rs | 5 +- 9 files changed, 54 insertions(+), 31 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 24f2c50e882..fad81600576 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -835,7 +835,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def = instance.map(|i| i.def); - if let Some(ty::InstanceDef::DropGlue(_, None)) = def { + if let Some( + ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None), + ) = def + { // Empty drop glue; a no-op. let target = target.unwrap(); return helper.funclet_br(self, bx, target, mergeable_succ); diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 5ccc0386c97..9eed7019782 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -65,7 +65,9 @@ impl<'tcx> MonoItem<'tcx> { match instance.def { // "Normal" functions size estimate: the number of // statements, plus one for the terminator. - InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { + InstanceDef::Item(..) + | InstanceDef::DropGlue(..) + | InstanceDef::AsyncDropGlueCtorShim(..) => { let mir = tcx.instance_mir(instance.def); mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index c7c4225c80e..4002d0da790 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -288,6 +288,7 @@ impl<'tcx> InstanceDef<'tcx> { let def_id = match *self { ty::InstanceDef::Item(def) => def, ty::InstanceDef::DropGlue(_, Some(_)) => return false, + ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => return false, ty::InstanceDef::ThreadLocalShim(_) => return false, _ => return true, }; @@ -357,11 +358,12 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::FnPtrAddrShim(..) | InstanceDef::FnPtrShim(..) | InstanceDef::DropGlue(_, Some(_)) - | InstanceDef::AsyncDropGlueCtorShim(..) => false, + | InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => false, InstanceDef::ClosureOnceShim { .. } | InstanceDef::ConstructCoroutineInClosureShim { .. } | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) + | InstanceDef::AsyncDropGlueCtorShim(..) | InstanceDef::Item(_) | InstanceDef::Intrinsic(..) | InstanceDef::ReifyShim(..) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index cd9d17cf930..2d83b9f8ef1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1340,7 +1340,7 @@ impl<'tcx> Ty<'tcx> { /// implementation. Returning `true` means nothing -- could be /// `Drop`, might not be. fn could_have_surface_drop(self) -> bool { - self.is_async_destructor_trivially_noop() + !self.is_async_destructor_trivially_noop() && !matches!( self.kind(), ty::Tuple(_) diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index a423e324781..80eadb9abdc 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -9,7 +9,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, CallSource, CastKind, Const, ConstOperand, ConstValue, Local, LocalDecl, MirSource, Operand, Place, PlaceElem, Rvalue, SourceInfo, Statement, StatementKind, - Terminator, TerminatorKind, UnwindAction, UnwindTerminateReason, + Terminator, TerminatorKind, UnwindAction, UnwindTerminateReason, RETURN_PLACE, }; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::util::Discr; @@ -67,9 +67,12 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { const MAX_STACK_LEN: usize = 2; fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Option>) -> Self { - // Assuming `async_drop_in_place::<()>` is the same as for any type with noop async destructor - let arg_ty = if let Some(ty) = self_ty { ty } else { tcx.types.unit }; - let sig = tcx.fn_sig(def_id).instantiate(tcx, &[arg_ty.into()]); + let args = if let Some(ty) = self_ty { + tcx.mk_args(&[ty.into()]) + } else { + ty::GenericArgs::identity_for_item(tcx, def_id) + }; + let sig = tcx.fn_sig(def_id).instantiate(tcx, args); let sig = tcx.instantiate_bound_regions_with_erased(sig); let span = tcx.def_span(def_id); @@ -113,7 +116,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { fn build(self) -> Body<'tcx> { let (tcx, def_id, Some(self_ty)) = (self.tcx, self.def_id, self.self_ty) else { - return self.build_noop(); + return self.build_zst_output(); }; let surface_drop_kind = || { @@ -258,8 +261,8 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { self.return_() } - fn build_noop(mut self) -> Body<'tcx> { - self.put_noop(); + fn build_zst_output(mut self) -> Body<'tcx> { + self.put_zst_output(); self.return_() } @@ -288,6 +291,15 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { self.return_() } + fn put_zst_output(&mut self) { + let return_ty = self.locals[RETURN_PLACE].ty; + self.put_operand(Operand::Constant(Box::new(ConstOperand { + span: self.span, + user_ty: None, + const_: Const::zero_sized(return_ty), + }))); + } + /// Puts `to_drop: *mut Self` on top of the stack. fn put_self(&mut self) { self.put_operand(Operand::Copy(Self::SELF_PTR.into())) @@ -464,23 +476,15 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { self.stack.len(), ) }; - const RETURN_LOCAL: Local = Local::from_u32(0); - - debug_assert_eq!( - output.ty(&self.locals, self.tcx), - self.self_ty.map(|ty| ty.async_destructor_ty(self.tcx, self.param_env)).unwrap_or_else( - || { - self.tcx - .fn_sig( - self.tcx.require_lang_item(LangItem::AsyncDropNoop, Some(self.span)), - ) - .instantiate_identity() - .output() - .no_bound_vars() - .unwrap() - } - ), - ); + #[cfg(debug_assertions)] + if let Some(ty) = self.self_ty { + debug_assert_eq!( + output.ty(&self.locals, self.tcx), + ty.async_destructor_ty(self.tcx, self.param_env), + "output async destructor types did not match for type: {ty:?}", + ); + } + let dead_storage = match &output { Operand::Move(place) => Some(Statement { source_info, @@ -492,7 +496,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { last_bb.statements.extend( iter::once(Statement { source_info, - kind: StatementKind::Assign(Box::new((RETURN_LOCAL.into(), Rvalue::Use(output)))), + kind: StatementKind::Assign(Box::new((RETURN_PLACE.into(), Rvalue::Use(output)))), }) .chain(dead_storage), ); diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 61bbedf9eec..fd31c020f89 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -500,6 +500,12 @@ impl<'tcx> Context for TablesWrapper<'tcx> { matches!(instance.def, ty::InstanceDef::DropGlue(_, None)) } + fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool { + let tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + matches!(instance.def, ty::InstanceDef::AsyncDropGlueCtorShim(_, None)) + } + fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance { let mut tables = self.0.borrow_mut(); let def_id = tables[def_id]; diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 400556a7d6a..c1661fa63a8 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -57,7 +57,7 @@ fn resolve_instance<'tcx>( } else if Some(def_id) == tcx.lang_items().async_drop_in_place_fn() { let ty = args.type_at(0); - if ty.is_async_destructor_noop(tcx, param_env) { + if !ty.is_async_destructor_noop(tcx, param_env) { match *ty.kind() { ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 94c552199bc..e82d1f4813e 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -158,6 +158,9 @@ pub trait Context { /// Check if this is an empty DropGlue shim. fn is_empty_drop_shim(&self, def: InstanceDef) -> bool; + /// Check if this is an empty AsyncDropGlueCtor shim. + fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool; + /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. fn mono_instance(&self, def_id: DefId) -> Instance; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index a032a180fcf..394038926f6 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -157,7 +157,10 @@ impl Instance { /// When generating code for a Drop terminator, users can ignore an empty drop glue. /// These shims are only needed to generate a valid Drop call done via VTable. pub fn is_empty_shim(&self) -> bool { - self.kind == InstanceKind::Shim && with(|cx| cx.is_empty_drop_shim(self.def)) + self.kind == InstanceKind::Shim + && with(|cx| { + cx.is_empty_drop_shim(self.def) || cx.is_empty_async_drop_ctor_shim(self.def) + }) } /// Try to constant evaluate the instance into a constant with the given type. -- cgit 1.4.1-3-g733a5