about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src')
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs6
-rw-r--r--compiler/rustc_ty_utils/src/common_traits.rs8
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs24
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs94
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs38
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs2
6 files changed, 155 insertions, 17 deletions
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 63ea035bd0e..2b49d7ac8b5 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -551,8 +551,10 @@ fn fn_abi_new_uncached<'tcx>(
         extra_args
     };
 
-    let is_drop_in_place =
-        determined_fn_def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::DropInPlace));
+    let is_drop_in_place = determined_fn_def_id.is_some_and(|def_id| {
+        tcx.is_lang_item(def_id, LangItem::DropInPlace)
+            || tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace)
+    });
 
     let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
         let span = tracing::debug_span!("arg_of");
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index 20646cf9a82..bb2c4172b08 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -29,6 +29,13 @@ fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, T
     is_item_raw(tcx, query, LangItem::Unpin)
 }
 
+fn is_async_drop_raw<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
+) -> bool {
+    is_item_raw(tcx, query, LangItem::AsyncDrop)
+}
+
 fn is_item_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
@@ -46,6 +53,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         is_sized_raw,
         is_freeze_raw,
         is_unpin_raw,
+        is_async_drop_raw,
         ..*providers
     };
 }
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 66c18bed5e7..da83566dad0 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -5,7 +5,6 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
-use rustc_middle::ty::util::AsyncDropGlueMorphology;
 use rustc_middle::ty::{
     self, ClosureKind, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt,
 };
@@ -41,20 +40,26 @@ fn resolve_instance_raw<'tcx>(
             if ty.needs_drop(tcx, typing_env) {
                 debug!(" => nontrivial drop glue");
                 match *ty.kind() {
+                    ty::Coroutine(coroutine_def_id, ..) => {
+                        // FIXME: sync drop of coroutine with async drop (generate both versions?)
+                        // Currently just ignored
+                        if tcx.optimized_mir(coroutine_def_id).coroutine_drop_async().is_some() {
+                            ty::InstanceKind::DropGlue(def_id, None)
+                        } else {
+                            ty::InstanceKind::DropGlue(def_id, Some(ty))
+                        }
+                    }
                     ty::Closure(..)
                     | ty::CoroutineClosure(..)
-                    | ty::Coroutine(..)
                     | ty::Tuple(..)
                     | ty::Adt(..)
                     | ty::Dynamic(..)
                     | ty::Array(..)
                     | ty::Slice(..)
-                    | ty::UnsafeBinder(..) => {}
+                    | ty::UnsafeBinder(..) => ty::InstanceKind::DropGlue(def_id, Some(ty)),
                     // Drop shims can only be built from ADTs.
                     _ => return Ok(None),
                 }
-
-                ty::InstanceKind::DropGlue(def_id, Some(ty))
             } else {
                 debug!(" => trivial drop glue");
                 ty::InstanceKind::DropGlue(def_id, None)
@@ -62,7 +67,7 @@ fn resolve_instance_raw<'tcx>(
         } else if tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) {
             let ty = args.type_at(0);
 
-            if ty.async_drop_glue_morphology(tcx) != AsyncDropGlueMorphology::Noop {
+            if ty.needs_async_drop(tcx, typing_env) {
                 match *ty.kind() {
                     ty::Closure(..)
                     | ty::CoroutineClosure(..)
@@ -76,11 +81,14 @@ fn resolve_instance_raw<'tcx>(
                     _ => return Ok(None),
                 }
                 debug!(" => nontrivial async drop glue ctor");
-                ty::InstanceKind::AsyncDropGlueCtorShim(def_id, Some(ty))
+                ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty)
             } else {
                 debug!(" => trivial async drop glue ctor");
-                ty::InstanceKind::AsyncDropGlueCtorShim(def_id, None)
+                ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty)
             }
+        } else if tcx.is_async_drop_in_place_coroutine(def_id) {
+            let ty = args.type_at(0);
+            ty::InstanceKind::AsyncDropGlue(def_id, ty)
         } else {
             debug!(" => free item");
             ty::InstanceKind::Item(def_id)
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 1915ba623cb..908fcb14cb2 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -184,6 +184,10 @@ fn layout_of_uncached<'tcx>(
     }
 
     let tcx = cx.tcx();
+
+    // layout of `async_drop_in_place<T>::{closure}` in case,
+    // when T is a coroutine, contains this internal coroutine's ref
+
     let dl = cx.data_layout();
     let map_layout = |result: Result<_, _>| match result {
         Ok(layout) => Ok(tcx.mk_layout(layout)),
@@ -255,13 +259,95 @@ fn layout_of_uncached<'tcx>(
                         };
 
                         layout.largest_niche = Some(niche);
-
-                        tcx.mk_layout(layout)
                     } else {
                         bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
                     }
                 }
+                ty::PatternKind::Or(variants) => match *variants[0] {
+                    ty::PatternKind::Range { .. } => {
+                        if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
+                            let variants: Result<Vec<_>, _> = variants
+                                .iter()
+                                .map(|pat| match *pat {
+                                    ty::PatternKind::Range { start, end } => Ok((
+                                        extract_const_value(cx, ty, start)
+                                            .unwrap()
+                                            .try_to_bits(tcx, cx.typing_env)
+                                            .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
+                                        extract_const_value(cx, ty, end)
+                                            .unwrap()
+                                            .try_to_bits(tcx, cx.typing_env)
+                                            .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
+                                    )),
+                                    ty::PatternKind::Or(_) => {
+                                        unreachable!("mixed or patterns are not allowed")
+                                    }
+                                })
+                                .collect();
+                            let mut variants = variants?;
+                            if !scalar.is_signed() {
+                                let guar = tcx.dcx().err(format!(
+                                    "only signed integer base types are allowed for or-pattern pattern types at present"
+                                ));
+
+                                return Err(error(cx, LayoutError::ReferencesError(guar)));
+                            }
+                            variants.sort();
+                            if variants.len() != 2 {
+                                let guar = tcx
+                                .dcx()
+                                .err(format!("the only or-pattern types allowed are two range patterns that are directly connected at their overflow site"));
+
+                                return Err(error(cx, LayoutError::ReferencesError(guar)));
+                            }
+
+                            // first is the one starting at the signed in range min
+                            let mut first = variants[0];
+                            let mut second = variants[1];
+                            if second.0
+                                == layout.size.truncate(layout.size.signed_int_min() as u128)
+                            {
+                                (second, first) = (first, second);
+                            }
+
+                            if layout.size.sign_extend(first.1) >= layout.size.sign_extend(second.0)
+                            {
+                                let guar = tcx.dcx().err(format!(
+                                    "only non-overlapping pattern type ranges are allowed at present"
+                                ));
+
+                                return Err(error(cx, LayoutError::ReferencesError(guar)));
+                            }
+                            if layout.size.signed_int_max() as u128 != second.1 {
+                                let guar = tcx.dcx().err(format!(
+                                    "one pattern needs to end at `{ty}::MAX`, but was {} instead",
+                                    second.1
+                                ));
+
+                                return Err(error(cx, LayoutError::ReferencesError(guar)));
+                            }
+
+                            // Now generate a wrapping range (which aren't allowed in surface syntax).
+                            scalar.valid_range_mut().start = second.0;
+                            scalar.valid_range_mut().end = first.1;
+
+                            let niche = Niche {
+                                offset: Size::ZERO,
+                                value: scalar.primitive(),
+                                valid_range: scalar.valid_range(cx),
+                            };
+
+                            layout.largest_niche = Some(niche);
+                        } else {
+                            bug!(
+                                "pattern type with range but not scalar layout: {ty:?}, {layout:?}"
+                            )
+                        }
+                    }
+                    ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"),
+                },
             }
+            tcx.mk_layout(layout)
         }
 
         // Basic scalars.
@@ -406,7 +492,7 @@ fn layout_of_uncached<'tcx>(
         ty::Coroutine(def_id, args) => {
             use rustc_middle::ty::layout::PrimitiveExt as _;
 
-            let Some(info) = tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()) else {
+            let Some(info) = tcx.coroutine_layout(def_id, args) else {
                 return Err(error(cx, LayoutError::Unknown(ty)));
             };
 
@@ -770,7 +856,7 @@ fn variant_info_for_coroutine<'tcx>(
         return (vec![], None);
     };
 
-    let coroutine = cx.tcx().coroutine_layout(def_id, args.as_coroutine().kind_ty()).unwrap();
+    let coroutine = cx.tcx().coroutine_layout(def_id, args).unwrap();
     let upvar_names = cx.tcx().closure_saved_names_of_captured_variables(def_id);
 
     let mut upvars_size = Size::ZERO;
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 52955ec59a4..c3b04c20f4b 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -42,11 +42,11 @@ fn needs_async_drop_raw<'tcx>(
     let adt_has_async_dtor =
         |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant);
     let res = drop_tys_helper(tcx, query.value, query.typing_env, adt_has_async_dtor, false, false)
-        .filter(filter_array_elements(tcx, query.typing_env))
+        .filter(filter_array_elements_async(tcx, query.typing_env))
         .next()
         .is_some();
 
-    debug!("needs_drop_raw({:?}) = {:?}", query, res);
+    debug!("needs_async_drop_raw({:?}) = {:?}", query, res);
     res
 }
 
@@ -66,6 +66,18 @@ fn filter_array_elements<'tcx>(
         Err(AlwaysRequiresDrop) => true,
     }
 }
+fn filter_array_elements_async<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
+) -> impl Fn(&Result<Ty<'tcx>, AlwaysRequiresDrop>) -> bool {
+    move |ty| match ty {
+        Ok(ty) => match *ty.kind() {
+            ty::Array(elem, _) => tcx.needs_async_drop_raw(typing_env.as_query_input(elem)),
+            _ => true,
+        },
+        Err(AlwaysRequiresDrop) => true,
+    }
+}
 
 fn has_significant_drop_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -414,6 +426,27 @@ fn adt_drop_tys<'tcx>(
     .collect::<Result<Vec<_>, _>>()
     .map(|components| tcx.mk_type_list(&components))
 }
+
+fn adt_async_drop_tys<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
+    // This is for the "adt_async_drop_tys" query, that considers all `AsyncDrop` impls.
+    let adt_has_dtor =
+        |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant);
+    // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_args)`
+    drop_tys_helper(
+        tcx,
+        tcx.type_of(def_id).instantiate_identity(),
+        ty::TypingEnv::non_body_analysis(tcx, def_id),
+        adt_has_dtor,
+        false,
+        false,
+    )
+    .collect::<Result<Vec<_>, _>>()
+    .map(|components| tcx.mk_type_list(&components))
+}
+
 // If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed
 // a `tcx.make_ty(def, identity_args)` and as such it is legal to instantiate the generic parameters
 // of the ADT into the outputted `ty`s.
@@ -458,6 +491,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         needs_async_drop_raw,
         has_significant_drop_raw,
         adt_drop_tys,
+        adt_async_drop_tys,
         adt_significant_drop_tys,
         list_significant_drop_tys,
         ..*providers
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index cd730aeeea9..841f602d985 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -223,7 +223,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
             }
             // Skips type aliases, as they are meant to be transparent.
             // FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly?
-            ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
+            ty::Alias(ty::Free, alias_ty) if alias_ty.def_id.is_local() => {
                 self.tcx
                     .type_of(alias_ty.def_id)
                     .instantiate(self.tcx, alias_ty.args)