Skip to content

Commit 0ac2aaa

Browse files
committed
Prereq6 for async drop - templated coroutine processing and layout
1 parent 8dd8360 commit 0ac2aaa

File tree

12 files changed

+271
-40
lines changed

12 files changed

+271
-40
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -669,8 +669,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
669669
_ => unreachable!(),
670670
};
671671

672-
let coroutine_layout =
673-
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
672+
let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();
674673

675674
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
676675
let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,8 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
146146
DIFlags::FlagZero,
147147
),
148148
|cx, coroutine_type_di_node| {
149-
let coroutine_layout = cx
150-
.tcx
151-
.coroutine_layout(coroutine_def_id, coroutine_args.as_coroutine().kind_ty())
152-
.unwrap();
149+
let coroutine_layout =
150+
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args).unwrap();
153151

154152
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
155153
coroutine_type_and_layout.variants

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ macro_rules! arena_types {
99
($macro:path) => (
1010
$macro!([
1111
[] layout: rustc_target::abi::LayoutS<rustc_target::abi::FieldIdx, rustc_target::abi::VariantIdx>,
12+
[] proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>,
1213
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
1314
// AdtDef are interned and compared by address
1415
[decode] adt_def: rustc_middle::ty::AdtDefData,

compiler/rustc_middle/src/query/mod.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,13 @@ rustc_queries! {
515515
desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) }
516516
}
517517

518+
query templated_mir_drops_elaborated_and_const_checked(ty: Ty<'tcx>)
519+
-> &'tcx Steal<mir::Body<'tcx>>
520+
{
521+
no_hash
522+
desc { |tcx| "elaborating drops for templated mir `{}`", ty }
523+
}
524+
518525
query mir_for_ctfe(
519526
key: DefId
520527
) -> &'tcx mir::Body<'tcx> {
@@ -579,6 +586,11 @@ rustc_queries! {
579586
desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) }
580587
}
581588

589+
/// MIR for templated coroutine after our optimization passes have run.
590+
query templated_optimized_mir(ty: Ty<'tcx>) -> &'tcx mir::Body<'tcx> {
591+
desc { |tcx| "optimizing templated MIR for `{}`", ty }
592+
}
593+
582594
/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
583595
/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations
584596
/// have had a chance to potentially remove some of them.
@@ -1161,7 +1173,11 @@ rustc_queries! {
11611173
/// Generates a MIR body for the shim.
11621174
query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> {
11631175
arena_cache
1164-
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
1176+
desc {
1177+
|tcx| "generating MIR shim for `{}`, instance={:?}",
1178+
tcx.def_path_str(key.def_id()),
1179+
key
1180+
}
11651181
}
11661182

11671183
/// The `symbol_name` query provides the symbol name for calling a

compiler/rustc_middle/src/ty/layout.rs

+49-14
Original file line numberDiff line numberDiff line change
@@ -896,22 +896,57 @@ where
896896
i,
897897
),
898898

899-
ty::Coroutine(def_id, args) => match this.variants {
900-
Variants::Single { index } => TyMaybeWithLayout::Ty(
901-
args.as_coroutine()
902-
.state_tys(def_id, tcx)
903-
.nth(index.as_usize())
904-
.unwrap()
905-
.nth(i)
906-
.unwrap(),
907-
),
908-
Variants::Multiple { tag, tag_field, .. } => {
909-
if i == tag_field {
910-
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
899+
ty::Coroutine(def_id, args) => {
900+
// layout of `async_drop_in_place<T>::{closure}` in case,
901+
// when T is a coroutine, contains this internal coroutine's ref
902+
if tcx.is_templated_coroutine(def_id) {
903+
fn find_impl_coroutine<'tcx>(
904+
tcx: TyCtxt<'tcx>,
905+
mut cor_ty: Ty<'tcx>,
906+
) -> Ty<'tcx> {
907+
let mut ty = cor_ty;
908+
loop {
909+
if let ty::Coroutine(def_id, args) = ty.kind() {
910+
cor_ty = ty;
911+
if tcx.is_templated_coroutine(*def_id) {
912+
ty = args.first().unwrap().expect_ty();
913+
continue;
914+
} else {
915+
return cor_ty;
916+
}
917+
} else {
918+
return cor_ty;
919+
}
920+
}
921+
}
922+
let arg_cor_ty = args.first().unwrap().expect_ty();
923+
if arg_cor_ty.is_coroutine() {
924+
assert!(i == 0);
925+
let impl_cor_ty = find_impl_coroutine(tcx, arg_cor_ty);
926+
return TyMaybeWithLayout::Ty(Ty::new_mut_ref(
927+
tcx,
928+
tcx.lifetimes.re_static,
929+
impl_cor_ty,
930+
));
911931
}
912-
TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
913932
}
914-
},
933+
match this.variants {
934+
Variants::Single { index } => TyMaybeWithLayout::Ty(
935+
args.as_coroutine()
936+
.state_tys(def_id, tcx)
937+
.nth(index.as_usize())
938+
.unwrap()
939+
.nth(i)
940+
.unwrap(),
941+
),
942+
Variants::Multiple { tag, tag_field, .. } => {
943+
if i == tag_field {
944+
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
945+
}
946+
TyMaybeWithLayout::Ty(args.as_coroutine().prefix_tys()[i])
947+
}
948+
}
949+
}
915950

916951
ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]),
917952

compiler/rustc_middle/src/ty/mod.rs

+66-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
3535
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
3636
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
3737
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
38+
use rustc_index::bit_set::BitMatrix;
3839
use rustc_index::IndexVec;
3940
use rustc_macros::{
4041
extension, Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable,
@@ -109,7 +110,7 @@ pub use self::IntVarValue::*;
109110
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
110111
use crate::metadata::ModChild;
111112
use crate::middle::privacy::EffectiveVisibilities;
112-
use crate::mir::{Body, CoroutineLayout};
113+
use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, CoroutineSavedTy, SourceInfo};
113114
use crate::query::Providers;
114115
use crate::traits::{self, Reveal};
115116
use crate::ty;
@@ -1764,7 +1765,7 @@ impl<'tcx> TyCtxt<'tcx> {
17641765
| ty::InstanceKind::FnPtrAddrShim(..)
17651766
| ty::InstanceKind::AsyncDropGlueCtorShim(..) => self.mir_shims(instance),
17661767
// async drop glue should be processed specifically, as a templated coroutine
1767-
ty::InstanceKind::AsyncDropGlue(_, _ty) => todo!(),
1768+
ty::InstanceKind::AsyncDropGlue(_, ty) => self.templated_optimized_mir(ty),
17681769
}
17691770
}
17701771

@@ -1844,16 +1845,17 @@ impl<'tcx> TyCtxt<'tcx> {
18441845
self.def_kind(trait_def_id) == DefKind::TraitAlias
18451846
}
18461847

1847-
/// Returns layout of a coroutine. Layout might be unavailable if the
1848+
/// Returns layout of a non-templated coroutine. Layout might be unavailable if the
18481849
/// coroutine is tainted by errors.
18491850
///
18501851
/// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
18511852
/// e.g. `args.as_coroutine().kind_ty()`.
1852-
pub fn coroutine_layout(
1853+
pub fn ordinary_coroutine_layout(
18531854
self,
18541855
def_id: DefId,
18551856
coroutine_kind_ty: Ty<'tcx>,
18561857
) -> Option<&'tcx CoroutineLayout<'tcx>> {
1858+
debug_assert_ne!(Some(def_id), self.lang_items().async_drop_in_place_poll_fn());
18571859
let mir = self.optimized_mir(def_id);
18581860
// Regular coroutine
18591861
if coroutine_kind_ty.is_unit() {
@@ -1882,6 +1884,66 @@ impl<'tcx> TyCtxt<'tcx> {
18821884
}
18831885
}
18841886

1887+
/// Returns layout of a templated coroutine. Layout might be unavailable if the
1888+
/// coroutine is tainted by errors. Atm, the only templated coroutine is
1889+
/// `async_drop_in_place<T>::{closure}` returned from `async fn async_drop_in_place<T>(..)`.
1890+
pub fn templated_coroutine_layout(self, ty: Ty<'tcx>) -> Option<&'tcx CoroutineLayout<'tcx>> {
1891+
self.templated_optimized_mir(ty).coroutine_layout_raw()
1892+
}
1893+
1894+
/// Returns layout of a templated (or not) coroutine. Layout might be unavailable if the
1895+
/// coroutine is tainted by errors.
1896+
pub fn coroutine_layout(
1897+
self,
1898+
def_id: DefId,
1899+
args: GenericArgsRef<'tcx>,
1900+
) -> Option<&'tcx CoroutineLayout<'tcx>> {
1901+
if Some(def_id) == self.lang_items().async_drop_in_place_poll_fn() {
1902+
fn find_impl_coroutine<'tcx>(tcx: TyCtxt<'tcx>, mut cor_ty: Ty<'tcx>) -> Ty<'tcx> {
1903+
let mut ty = cor_ty;
1904+
loop {
1905+
if let ty::Coroutine(def_id, args) = ty.kind() {
1906+
cor_ty = ty;
1907+
if tcx.is_templated_coroutine(*def_id) {
1908+
ty = args.first().unwrap().expect_ty();
1909+
continue;
1910+
} else {
1911+
return cor_ty;
1912+
}
1913+
} else {
1914+
return cor_ty;
1915+
}
1916+
}
1917+
}
1918+
// layout of `async_drop_in_place<T>::{closure}` in case,
1919+
// when T is a coroutine, contains this internal coroutine's ref
1920+
let arg_cor_ty = args.first().unwrap().expect_ty();
1921+
if arg_cor_ty.is_coroutine() {
1922+
let impl_cor_ty = find_impl_coroutine(self, arg_cor_ty);
1923+
let impl_ref = Ty::new_mut_ref(self, self.lifetimes.re_static, impl_cor_ty);
1924+
let span = self.def_span(def_id);
1925+
let source_info = SourceInfo::outermost(span);
1926+
let proxy_layout = CoroutineLayout {
1927+
field_tys: [CoroutineSavedTy {
1928+
ty: impl_ref,
1929+
source_info,
1930+
ignore_for_traits: true,
1931+
}]
1932+
.into(),
1933+
field_names: [None].into(),
1934+
variant_fields: [IndexVec::from([CoroutineSavedLocal::ZERO])].into(),
1935+
variant_source_info: [source_info].into(),
1936+
storage_conflicts: BitMatrix::new(1, 1),
1937+
};
1938+
return Some(self.arena.alloc(proxy_layout));
1939+
} else {
1940+
self.templated_coroutine_layout(Ty::new_coroutine(self, def_id, args))
1941+
}
1942+
} else {
1943+
self.ordinary_coroutine_layout(def_id, args.as_coroutine().kind_ty())
1944+
}
1945+
}
1946+
18851947
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
18861948
/// If it implements no trait, returns `None`.
18871949
pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {

compiler/rustc_middle/src/ty/sty.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
7878
#[inline]
7979
fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
8080
// FIXME requires optimized MIR
81-
FIRST_VARIANT
82-
..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index()
81+
FIRST_VARIANT..tcx.coroutine_layout(def_id, self.args).unwrap().variant_fields.next_index()
8382
}
8483

8584
/// The discriminant for the given variant. Panics if the `variant_index` is
@@ -139,10 +138,14 @@ impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
139138
def_id: DefId,
140139
tcx: TyCtxt<'tcx>,
141140
) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
142-
let layout = tcx.coroutine_layout(def_id, self.kind_ty()).unwrap();
141+
let layout = tcx.coroutine_layout(def_id, self.args).unwrap();
143142
layout.variant_fields.iter().map(move |variant| {
144143
variant.iter().map(move |field| {
145-
ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)
144+
if tcx.is_templated_coroutine(def_id) {
145+
layout.field_tys[*field].ty
146+
} else {
147+
ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)
148+
}
146149
})
147150
})
148151
}

compiler/rustc_mir_dataflow/src/value_analysis.rs

+3
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,9 @@ impl<'tcx> Map<'tcx> {
792792
if exclude.contains(local) {
793793
continue;
794794
}
795+
if decl.ty.is_templated_coroutine(tcx) {
796+
continue;
797+
}
795798

796799
// Create a place for the local.
797800
debug_assert!(self.locals[local].is_none());

compiler/rustc_mir_transform/src/known_panics_lint.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,11 @@ impl CanConstProp {
885885
};
886886
for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
887887
let ty = body.local_decls[local].ty;
888-
if ty.is_union() {
888+
if ty.is_templated_coroutine(tcx) {
889+
// No const propagation for templated coroutine (AsyncDropGlue)
890+
*val = ConstPropMode::NoPropagation;
891+
continue;
892+
} else if ty.is_union() {
889893
// Unions are incompatible with the current implementation of
890894
// const prop because Rust has no concept of an active
891895
// variant of a union

0 commit comments

Comments
 (0)