about summary refs log tree commit diff
path: root/compiler/rustc_monomorphize/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_monomorphize/src')
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs71
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs6
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs3
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs45
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/move_check.rs39
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs12
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/autodiff.rs32
7 files changed, 131 insertions, 77 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 6e676ac6b8d..76dad6b3571 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -688,7 +688,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                 let target_ty = self.monomorphize(target_ty);
                 let source_ty = self.monomorphize(source_ty);
                 let (source_ty, target_ty) =
-                    find_vtable_types_for_unsizing(self.tcx.at(span), source_ty, target_ty);
+                    find_tails_for_unsizing(self.tcx.at(span), source_ty, target_ty);
                 // This could also be a different Unsize instruction, like
                 // from a fixed sized array to a slice. But we are only
                 // interested in things that produce a vtable.
@@ -929,14 +929,16 @@ fn visit_instance_use<'tcx>(
         ty::InstanceKind::ThreadLocalShim(..) => {
             bug!("{:?} being reified", instance);
         }
-        ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => {
+        ty::InstanceKind::DropGlue(_, 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::InstanceKind::DropGlue(_, Some(_))
-        | ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(_))
+        | ty::InstanceKind::FutureDropPollShim(..)
+        | ty::InstanceKind::AsyncDropGlue(_, _)
+        | ty::InstanceKind::AsyncDropGlueCtorShim(_, _)
         | ty::InstanceKind::VTableShim(..)
         | ty::InstanceKind::ReifyShim(..)
         | ty::InstanceKind::ClosureOnceShim { .. }
@@ -1037,36 +1039,35 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
 ///
 /// Finally, there is also the case of custom unsizing coercions, e.g., for
 /// smart pointers such as `Rc` and `Arc`.
-fn find_vtable_types_for_unsizing<'tcx>(
+fn find_tails_for_unsizing<'tcx>(
     tcx: TyCtxtAt<'tcx>,
     source_ty: Ty<'tcx>,
     target_ty: Ty<'tcx>,
 ) -> (Ty<'tcx>, Ty<'tcx>) {
-    let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
-        let typing_env = ty::TypingEnv::fully_monomorphized();
-        if tcx.type_has_metadata(inner_source, typing_env) {
-            (inner_source, inner_target)
-        } else {
-            tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env)
-        }
-    };
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+    debug_assert!(!source_ty.has_param(), "{source_ty} should be fully monomorphic");
+    debug_assert!(!target_ty.has_param(), "{target_ty} should be fully monomorphic");
 
     match (source_ty.kind(), target_ty.kind()) {
-        (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
-        | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b),
+        (
+            &ty::Ref(_, source_pointee, _),
+            &ty::Ref(_, target_pointee, _) | &ty::RawPtr(target_pointee, _),
+        )
+        | (&ty::RawPtr(source_pointee, _), &ty::RawPtr(target_pointee, _)) => {
+            tcx.struct_lockstep_tails_for_codegen(source_pointee, target_pointee, typing_env)
+        }
+
+        // `Box<T>` could go through the ADT code below, b/c it'll unpeel to `Unique<T>`,
+        // and eventually bottom out in a raw ref, but we can micro-optimize it here.
         (_, _)
             if let Some(source_boxed) = source_ty.boxed_ty()
                 && let Some(target_boxed) = target_ty.boxed_ty() =>
         {
-            ptr_vtable(source_boxed, target_boxed)
+            tcx.struct_lockstep_tails_for_codegen(source_boxed, target_boxed, typing_env)
         }
 
-        // T as dyn* Trait
-        (_, &ty::Dynamic(_, _, ty::DynStar)) => ptr_vtable(source_ty, target_ty),
-
         (&ty::Adt(source_adt_def, source_args), &ty::Adt(target_adt_def, target_args)) => {
             assert_eq!(source_adt_def, target_adt_def);
-
             let CustomCoerceUnsized::Struct(coerce_index) =
                 match crate::custom_coerce_unsize_info(tcx, source_ty, target_ty) {
                     Ok(ccu) => ccu,
@@ -1075,21 +1076,23 @@ fn find_vtable_types_for_unsizing<'tcx>(
                         return (e, e);
                     }
                 };
+            let coerce_field = &source_adt_def.non_enum_variant().fields[coerce_index];
+            // We're getting a possibly unnormalized type, so normalize it.
+            let source_field =
+                tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, source_args));
+            let target_field =
+                tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, target_args));
+            find_tails_for_unsizing(tcx, source_field, target_field)
+        }
 
-            let source_fields = &source_adt_def.non_enum_variant().fields;
-            let target_fields = &target_adt_def.non_enum_variant().fields;
-
-            assert!(
-                coerce_index.index() < source_fields.len()
-                    && source_fields.len() == target_fields.len()
-            );
+        // `T` as `dyn* Trait` unsizes *directly*.
+        //
+        // FIXME(dyn_star): This case is a bit awkward, b/c we're not really computing
+        // a tail here. We probably should handle this separately in the *caller* of
+        // this function, rather than returning something that is semantically different
+        // than what we return above.
+        (_, &ty::Dynamic(_, _, ty::DynStar)) => (source_ty, target_ty),
 
-            find_vtable_types_for_unsizing(
-                tcx,
-                source_fields[coerce_index].ty(*tcx, source_args),
-                target_fields[coerce_index].ty(*tcx, target_args),
-            )
-        }
         _ => bug!(
             "find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
             source_ty,
@@ -1308,7 +1311,7 @@ fn visit_mentioned_item<'tcx>(
         }
         MentionedItem::UnsizeCast { source_ty, target_ty } => {
             let (source_ty, target_ty) =
-                find_vtable_types_for_unsizing(tcx.at(span), source_ty, target_ty);
+                find_tails_for_unsizing(tcx.at(span), source_ty, target_ty);
             // This could also be a different Unsize instruction, like
             // from a fixed sized array to a slice. But we are only
             // interested in things that produce a vtable.
@@ -1689,7 +1692,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
             let mut recursion_depths = DefIdMap::default();
             collect_items_rec(
                 tcx,
-                dummy_spanned(root),
+                dummy_spanned(*root),
                 &state,
                 &mut recursion_depths,
                 recursion_limit,
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index adfe096f0cd..0dd20bbb35f 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -70,10 +70,11 @@ pub(crate) struct UnknownCguCollectionMode<'a> {
     pub mode: &'a str,
 }
 
-#[derive(LintDiagnostic)]
+#[derive(Diagnostic)]
 #[diag(monomorphize_abi_error_disabled_vector_type)]
 #[help]
 pub(crate) struct AbiErrorDisabledVectorType<'a> {
+    #[primary_span]
     #[label]
     pub span: Span,
     pub required_feature: &'a str,
@@ -82,9 +83,10 @@ pub(crate) struct AbiErrorDisabledVectorType<'a> {
     pub is_call: bool,
 }
 
-#[derive(LintDiagnostic)]
+#[derive(Diagnostic)]
 #[diag(monomorphize_abi_error_unsupported_vector_type)]
 pub(crate) struct AbiErrorUnsupportedVectorType<'a> {
+    #[primary_span]
     #[label]
     pub span: Span,
     pub ty: Ty<'a>,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 5dbae50c499..8469e0f17a6 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,10 +1,9 @@
 // tidy-alphabetical-start
-#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
+#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(array_windows)]
 #![feature(file_buffered)]
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
-#![feature(let_chains)]
 // tidy-alphabetical-end
 
 use rustc_hir::lang_items::LangItem;
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 0f5bdc8d768..cfeaee07776 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -5,7 +5,7 @@ use rustc_hir::{CRATE_HIR_ID, HirId};
 use rustc_middle::mir::{self, Location, traversal};
 use rustc_middle::ty::layout::LayoutCx;
 use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
-use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI};
+use rustc_session::lint::builtin::WASM_C_ABI;
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
@@ -50,34 +50,24 @@ fn do_check_simd_vector_abi<'tcx>(
             let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
                 Some((_, feature)) => feature,
                 None => {
-                    let (span, hir_id) = loc();
-                    tcx.emit_node_span_lint(
-                        ABI_UNSUPPORTED_VECTOR_TYPES,
-                        hir_id,
+                    let (span, _hir_id) = loc();
+                    tcx.dcx().emit_err(errors::AbiErrorUnsupportedVectorType {
                         span,
-                        errors::AbiErrorUnsupportedVectorType {
-                            span,
-                            ty: arg_abi.layout.ty,
-                            is_call,
-                        },
-                    );
+                        ty: arg_abi.layout.ty,
+                        is_call,
+                    });
                     continue;
                 }
             };
             if !have_feature(Symbol::intern(feature)) {
                 // Emit error.
-                let (span, hir_id) = loc();
-                tcx.emit_node_span_lint(
-                    ABI_UNSUPPORTED_VECTOR_TYPES,
-                    hir_id,
+                let (span, _hir_id) = loc();
+                tcx.dcx().emit_err(errors::AbiErrorDisabledVectorType {
                     span,
-                    errors::AbiErrorDisabledVectorType {
-                        span,
-                        required_feature: feature,
-                        ty: arg_abi.layout.ty,
-                        is_call,
-                    },
-                );
+                    required_feature: feature,
+                    ty: arg_abi.layout.ty,
+                    is_call,
+                });
             }
         }
     }
@@ -99,6 +89,12 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
         return true;
     }
 
+    // Both the old and the new ABIs treat vector types like `v128` the same
+    // way.
+    if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) {
+        return true;
+    }
+
     // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
     if arg.layout.is_aggregate() {
         let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
@@ -111,6 +107,11 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool
         }
     }
 
+    // Zero-sized types are dropped in both ABIs, so they're safe
+    if arg.layout.is_zst() {
+        return true;
+    }
+
     false
 }
 
diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
index 838bfdab1ea..7251ef478c6 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::visit::Visitor as MirVisitor;
 use rustc_middle::mir::{self, Location, traversal};
-use rustc_middle::ty::{self, AssocKind, Instance, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, AssocTag, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc_session::Limit;
 use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
 use rustc_span::source_map::Spanned;
@@ -148,11 +148,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> {
         span: Span,
     ) {
         let source_info = self.body.source_info(location);
-        for reported_span in &self.move_size_spans {
-            if reported_span.overlaps(span) {
-                return;
-            }
-        }
+
         let lint_root = source_info.scope.lint_root(&self.body.source_scopes);
         let Some(lint_root) = lint_root else {
             // This happens when the issue is in a function from a foreign crate that
@@ -162,22 +158,43 @@ impl<'tcx> MoveCheckVisitor<'tcx> {
             // but correct span? This would make the lint at least accept crate-level lint attributes.
             return;
         };
+
+        // If the source scope is inlined by the MIR inliner, report the lint on the call site.
+        let reported_span = self
+            .body
+            .source_scopes
+            .get(source_info.scope)
+            .and_then(|source_scope_data| source_scope_data.inlined)
+            .map(|(_, call_site)| call_site)
+            .unwrap_or(span);
+
+        for previously_reported_span in &self.move_size_spans {
+            if previously_reported_span.overlaps(reported_span) {
+                return;
+            }
+        }
+
         self.tcx.emit_node_span_lint(
             LARGE_ASSIGNMENTS,
             lint_root,
-            span,
-            LargeAssignmentsLint { span, size: too_large_size.bytes(), limit: limit as u64 },
+            reported_span,
+            LargeAssignmentsLint {
+                span: reported_span,
+                size: too_large_size.bytes(),
+                limit: limit as u64,
+            },
         );
-        self.move_size_spans.push(span);
+
+        self.move_size_spans.push(reported_span);
     }
 }
 
 fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
     for impl_def_id in tcx.inherent_impls(def_id) {
-        if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
+        if let Some(new) = tcx.associated_items(impl_def_id).find_by_ident_and_kind(
             tcx,
             fn_ident,
-            AssocKind::Fn,
+            AssocTag::Fn,
             def_id,
         ) {
             return Some(new.def_id);
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index b1b6f10e0fe..6948dceddf9 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -223,7 +223,7 @@ where
         match mono_item.instantiation_mode(cx.tcx) {
             InstantiationMode::GloballyShared { .. } => {}
             InstantiationMode::LocalCopy => {
-                if Some(mono_item.def_id()) != cx.tcx.lang_items().start_fn() {
+                if !cx.tcx.is_lang_item(mono_item.def_id(), LangItem::Start) {
                     continue;
                 }
             }
@@ -254,8 +254,9 @@ where
             always_export_generics,
         );
 
-        // We can't differentiate something that got inlined.
+        // We can't differentiate a function that got inlined.
         let autodiff_active = cfg!(llvm_enzyme)
+            && matches!(mono_item, MonoItem::Fn(_))
             && cx
                 .tcx
                 .codegen_fn_attrs(mono_item.def_id())
@@ -643,6 +644,8 @@ fn characteristic_def_id_of_mono_item<'tcx>(
                 | ty::InstanceKind::CloneShim(..)
                 | ty::InstanceKind::ThreadLocalShim(..)
                 | ty::InstanceKind::FnPtrAddrShim(..)
+                | ty::InstanceKind::FutureDropPollShim(..)
+                | ty::InstanceKind::AsyncDropGlue(..)
                 | ty::InstanceKind::AsyncDropGlueCtorShim(..) => return None,
             };
 
@@ -795,7 +798,9 @@ fn mono_item_visibility<'tcx>(
     let def_id = match instance.def {
         InstanceKind::Item(def_id)
         | InstanceKind::DropGlue(def_id, Some(_))
-        | InstanceKind::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id,
+        | InstanceKind::FutureDropPollShim(def_id, _, _)
+        | InstanceKind::AsyncDropGlue(def_id, _)
+        | InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id,
 
         // We match the visibility of statics here
         InstanceKind::ThreadLocalShim(def_id) => {
@@ -811,7 +816,6 @@ fn mono_item_visibility<'tcx>(
         | InstanceKind::ClosureOnceShim { .. }
         | InstanceKind::ConstructCoroutineInClosureShim { .. }
         | InstanceKind::DropGlue(..)
-        | InstanceKind::AsyncDropGlueCtorShim(..)
         | InstanceKind::CloneShim(..)
         | InstanceKind::FnPtrAddrShim(..) => return Visibility::Hidden,
     };
diff --git a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
index ebe0b258c1b..22d593b80b8 100644
--- a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
@@ -2,7 +2,7 @@ use rustc_ast::expand::autodiff_attrs::{AutoDiffItem, DiffActivity};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::bug;
 use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, PseudoCanonicalInput, Ty, TyCtxt, TypingEnv};
 use rustc_symbol_mangling::symbol_name_for_instance_in_crate;
 use tracing::{debug, trace};
 
@@ -22,23 +22,51 @@ fn adjust_activity_to_abi<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec
     for (i, ty) in sig.inputs().iter().enumerate() {
         if let Some(inner_ty) = ty.builtin_deref(true) {
             if inner_ty.is_slice() {
+                // Now we need to figure out the size of each slice element in memory to allow
+                // safety checks and usability improvements in the backend.
+                let sty = match inner_ty.builtin_index() {
+                    Some(sty) => sty,
+                    None => {
+                        panic!("slice element type unknown");
+                    }
+                };
+                let pci = PseudoCanonicalInput {
+                    typing_env: TypingEnv::fully_monomorphized(),
+                    value: sty,
+                };
+
+                let layout = tcx.layout_of(pci);
+                let elem_size = match layout {
+                    Ok(layout) => layout.size,
+                    Err(_) => {
+                        bug!("autodiff failed to compute slice element size");
+                    }
+                };
+                let elem_size: u32 = elem_size.bytes() as u32;
+
                 // We know that the length will be passed as extra arg.
                 if !da.is_empty() {
                     // We are looking at a slice. The length of that slice will become an
                     // extra integer on llvm level. Integers are always const.
                     // However, if the slice get's duplicated, we want to know to later check the
                     // size. So we mark the new size argument as FakeActivitySize.
+                    // There is one FakeActivitySize per slice, so for convenience we store the
+                    // slice element size in bytes in it. We will use the size in the backend.
                     let activity = match da[i] {
                         DiffActivity::DualOnly
                         | DiffActivity::Dual
+                        | DiffActivity::Dualv
                         | DiffActivity::DuplicatedOnly
-                        | DiffActivity::Duplicated => DiffActivity::FakeActivitySize,
+                        | DiffActivity::Duplicated => {
+                            DiffActivity::FakeActivitySize(Some(elem_size))
+                        }
                         DiffActivity::Const => DiffActivity::Const,
                         _ => bug!("unexpected activity for ptr/ref"),
                     };
                     new_activities.push(activity);
                     new_positions.push(i + 1);
                 }
+
                 continue;
             }
         }