summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_monomorphize/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_monomorphize/src
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_monomorphize/src')
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs166
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs4
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs31
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs14
4 files changed, 87 insertions, 128 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 1a9f0e835..65bdcf107 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -173,7 +173,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::mir::visit::Visitor as MirVisitor;
-use rustc_middle::mir::{self, Local, Location};
+use rustc_middle::mir::{self, Location};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -186,8 +186,9 @@ use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyC
use rustc_session::config::EntryFnType;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
use rustc_session::Limit;
-use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
+use rustc_span::source_map::{dummy_spanned, respan, Spanned};
use rustc_span::symbol::{sym, Ident};
+use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::Size;
use std::path::PathBuf;
@@ -432,7 +433,7 @@ fn collect_items_rec<'tcx>(
hir::InlineAsmOperand::SymFn { anon_const } => {
let fn_ty =
tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
- visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items, &[]);
+ visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
}
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
let instance = Instance::mono(tcx, *def_id);
@@ -593,11 +594,9 @@ struct MirUsedCollector<'a, 'tcx> {
instance: Instance<'tcx>,
/// Spans for move size lints already emitted. Helps avoid duplicate lints.
move_size_spans: Vec<Span>,
- /// If true, we should temporarily skip move size checks, because we are
- /// processing an operand to a `skip_move_check_fns` function call.
- skip_move_size_check: bool,
+ visiting_call_terminator: bool,
/// Set of functions for which it is OK to move large data into.
- skip_move_check_fns: Vec<DefId>,
+ skip_move_check_fns: Option<Vec<DefId>>,
}
impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
@@ -613,7 +612,20 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
)
}
- fn check_move_size(&mut self, limit: usize, operand: &mir::Operand<'tcx>, location: Location) {
+ fn check_operand_move_size(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
+ let limit = self.tcx.move_size_limit().0;
+ if limit == 0 {
+ return;
+ }
+
+ // This function is called by visit_operand() which visits _all_
+ // operands, including TerminatorKind::Call operands. But if
+ // check_fn_args_move_size() has been called, the operands have already
+ // been visited. Do not visit them again.
+ if self.visiting_call_terminator {
+ return;
+ }
+
let limit = Size::from_bytes(limit);
let ty = operand.ty(self.body, self.tcx);
let ty = self.monomorphize(ty);
@@ -651,6 +663,38 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
);
self.move_size_spans.push(source_info.span);
}
+
+ fn check_fn_args_move_size(
+ &mut self,
+ callee_ty: Ty<'tcx>,
+ args: &[mir::Operand<'tcx>],
+ location: Location,
+ ) {
+ let limit = self.tcx.move_size_limit();
+ if limit.0 == 0 {
+ return;
+ }
+
+ if args.is_empty() {
+ return;
+ }
+
+ // Allow large moves into container types that themselves are cheap to move
+ let ty::FnDef(def_id, _) = *callee_ty.kind() else {
+ return;
+ };
+ if self
+ .skip_move_check_fns
+ .get_or_insert_with(|| build_skip_move_check_fns(self.tcx))
+ .contains(&def_id)
+ {
+ return;
+ }
+
+ for arg in args {
+ self.check_operand_move_size(arg, location);
+ }
+ }
}
impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
@@ -696,14 +740,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
) => {
let fn_ty = operand.ty(self.body, self.tcx);
let fn_ty = self.monomorphize(fn_ty);
- visit_fn_use(
- self.tcx,
- fn_ty,
- false,
- span,
- &mut self.output,
- &self.skip_move_check_fns,
- );
+ visit_fn_use(self.tcx, fn_ty, false, span, &mut self.output);
}
mir::Rvalue::Cast(
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
@@ -775,17 +812,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
};
match terminator.kind {
- mir::TerminatorKind::Call { ref func, .. } => {
+ mir::TerminatorKind::Call { ref func, ref args, .. } => {
let callee_ty = func.ty(self.body, tcx);
let callee_ty = self.monomorphize(callee_ty);
- self.skip_move_size_check = visit_fn_use(
- self.tcx,
- callee_ty,
- true,
- source,
- &mut self.output,
- &self.skip_move_check_fns,
- )
+ self.check_fn_args_move_size(callee_ty, args, location);
+ visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
}
mir::TerminatorKind::Drop { ref place, .. } => {
let ty = place.ty(self.body, self.tcx).ty;
@@ -797,7 +828,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
match *op {
mir::InlineAsmOperand::SymFn { ref value } => {
let fn_ty = self.monomorphize(value.const_.ty());
- visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output, &[]);
+ visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output);
}
mir::InlineAsmOperand::SymStatic { def_id } => {
let instance = Instance::mono(self.tcx, def_id);
@@ -825,7 +856,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
| mir::TerminatorKind::UnwindResume
| mir::TerminatorKind::Return
| mir::TerminatorKind::Unreachable => {}
- mir::TerminatorKind::GeneratorDrop
+ mir::TerminatorKind::CoroutineDrop
| mir::TerminatorKind::Yield { .. }
| mir::TerminatorKind::FalseEdge { .. }
| mir::TerminatorKind::FalseUnwind { .. } => bug!(),
@@ -835,24 +866,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
push_mono_lang_item(self, reason.lang_item());
}
+ self.visiting_call_terminator = matches!(terminator.kind, mir::TerminatorKind::Call { .. });
self.super_terminator(terminator, location);
- self.skip_move_size_check = false;
+ self.visiting_call_terminator = false;
}
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
self.super_operand(operand, location);
- let move_size_limit = self.tcx.move_size_limit().0;
- if move_size_limit > 0 && !self.skip_move_size_check {
- self.check_move_size(move_size_limit, operand, location);
- }
- }
-
- fn visit_local(
- &mut self,
- _place_local: Local,
- _context: mir::visit::PlaceContext,
- _location: Location,
- ) {
+ self.check_operand_move_size(operand, location);
}
}
@@ -873,11 +894,8 @@ fn visit_fn_use<'tcx>(
is_direct_call: bool,
source: Span,
output: &mut MonoItems<'tcx>,
- skip_move_check_fns: &[DefId],
-) -> bool {
- let mut skip_move_size_check = false;
+) {
if let ty::FnDef(def_id, args) = *ty.kind() {
- skip_move_size_check = skip_move_check_fns.contains(&def_id);
let instance = if is_direct_call {
ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
} else {
@@ -888,7 +906,6 @@ fn visit_fn_use<'tcx>(
};
visit_instance_use(tcx, instance, is_direct_call, source, output);
}
- skip_move_size_check
}
fn visit_instance_use<'tcx>(
@@ -1196,7 +1213,7 @@ impl<'v> RootCollector<'_, 'v> {
}
fn is_root(&self, def_id: LocalDefId) -> bool {
- !item_requires_monomorphization(self.tcx, def_id)
+ !self.tcx.generics_of(def_id).requires_monomorphization(self.tcx)
&& match self.mode {
MonoItemCollectionMode::Eager => true,
MonoItemCollectionMode::Lazy => {
@@ -1259,11 +1276,6 @@ impl<'v> RootCollector<'_, 'v> {
}
}
-fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- let generics = tcx.generics_of(def_id);
- generics.requires_monomorphization(tcx)
-}
-
#[instrument(level = "debug", skip(tcx, output))]
fn create_mono_items_for_default_impls<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -1370,17 +1382,6 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
}
}
-fn add_assoc_fn<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: Option<DefId>,
- fn_ident: Ident,
- skip_move_check_fns: &mut Vec<DefId>,
-) {
- if let Some(def_id) = def_id.and_then(|def_id| assoc_fn_of_type(tcx, def_id, fn_ident)) {
- skip_move_check_fns.push(def_id);
- }
-}
-
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(
@@ -1395,6 +1396,19 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) ->
return None;
}
+fn build_skip_move_check_fns(tcx: TyCtxt<'_>) -> Vec<DefId> {
+ let fns = [
+ (tcx.lang_items().owned_box(), "new"),
+ (tcx.get_diagnostic_item(sym::Rc), "new"),
+ (tcx.get_diagnostic_item(sym::Arc), "new"),
+ ];
+ fns.into_iter()
+ .filter_map(|(def_id, fn_name)| {
+ def_id.and_then(|def_id| assoc_fn_of_type(tcx, def_id, Ident::from_str(fn_name)))
+ })
+ .collect::<Vec<_>>()
+}
+
/// Scans the MIR in order to find function calls, closures, and drop-glue.
#[instrument(skip(tcx, output), level = "debug")]
fn collect_used_items<'tcx>(
@@ -1404,36 +1418,16 @@ fn collect_used_items<'tcx>(
) {
let body = tcx.instance_mir(instance.def);
- let mut skip_move_check_fns = vec![];
- if tcx.move_size_limit().0 > 0 {
- add_assoc_fn(
- tcx,
- tcx.lang_items().owned_box(),
- Ident::from_str("new"),
- &mut skip_move_check_fns,
- );
- add_assoc_fn(
- tcx,
- tcx.get_diagnostic_item(sym::Arc),
- Ident::from_str("new"),
- &mut skip_move_check_fns,
- );
- add_assoc_fn(
- tcx,
- tcx.get_diagnostic_item(sym::Rc),
- Ident::from_str("new"),
- &mut skip_move_check_fns,
- );
- }
-
+ // Here we rely on the visitor also visiting `required_consts`, so that we evaluate them
+ // and abort compilation if any of them errors.
MirUsedCollector {
tcx,
body: &body,
output,
instance,
move_size_spans: vec![],
- skip_move_size_check: false,
- skip_move_check_fns,
+ visiting_call_terminator: false,
+ skip_move_check_fns: None,
}
.visit_body(&body);
}
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index fdcc95f13..d242a7bae 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -76,10 +76,6 @@ pub struct LargeAssignmentsLint {
}
#[derive(Diagnostic)]
-#[diag(monomorphize_unknown_partition_strategy)]
-pub struct UnknownPartitionStrategy;
-
-#[derive(Diagnostic)]
#[diag(monomorphize_symbol_already_defined)]
pub struct SymbolAlreadyDefined {
#[primary_span]
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 1d8cbe0e2..4009e2892 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -105,7 +105,6 @@ use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
use rustc_hir::definitions::DefPathDataName;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
-use rustc_middle::mir;
use rustc_middle::mir::mono::{
CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
Visibility,
@@ -1279,38 +1278,8 @@ fn dump_mono_items_stats<'tcx>(
Ok(())
}
-fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
- let (items, cgus) = tcx.collect_and_partition_mono_items(());
- let mut visited = DefIdSet::default();
- let mut result = items.clone();
-
- for cgu in cgus {
- for item in cgu.items().keys() {
- if let MonoItem::Fn(ref instance) = item {
- let did = instance.def_id();
- if !visited.insert(did) {
- continue;
- }
- let body = tcx.instance_mir(instance.def);
- for block in body.basic_blocks.iter() {
- for statement in &block.statements {
- let mir::StatementKind::Coverage(_) = statement.kind else { continue };
- let scope = statement.source_info.scope;
- if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
- result.insert(inlined.def_id());
- }
- }
- }
- }
- }
- }
-
- tcx.arena.alloc(result)
-}
-
pub fn provide(providers: &mut Providers) {
providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
- providers.codegened_and_inlined_items = codegened_and_inlined_items;
providers.is_codegened_item = |tcx, def_id| {
let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 6c206a6ba..a3b35eab4 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -131,7 +131,7 @@ fn mark_used_by_default_parameters<'tcx>(
unused_parameters: &mut UnusedGenericParams,
) {
match tcx.def_kind(def_id) {
- DefKind::Closure | DefKind::Generator => {
+ DefKind::Closure | DefKind::Coroutine => {
for param in &generics.params {
debug!(?param, "(closure/gen)");
unused_parameters.mark_used(param.index);
@@ -227,7 +227,7 @@ struct MarkUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
/// Invoke `unused_generic_params` on a body contained within the current item (e.g.
- /// a closure, generator or constant).
+ /// a closure, coroutine or constant).
#[instrument(level = "debug", skip(self, def_id, args))]
fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
let instance = ty::InstanceDef::Item(def_id);
@@ -248,8 +248,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
if local == Local::from_usize(1) {
let def_kind = self.tcx.def_kind(self.def_id);
- if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
- // Skip visiting the closure/generator that is currently being processed. This only
+ if matches!(def_kind, DefKind::Closure | DefKind::Coroutine) {
+ // Skip visiting the closure/coroutine that is currently being processed. This only
// happens because the first argument to the closure is a reference to itself and
// that will call `visit_args`, resulting in each generic parameter captured being
// considered used by default.
@@ -319,14 +319,14 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
}
match *ty.kind() {
- ty::Closure(def_id, args) | ty::Generator(def_id, args, ..) => {
+ ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => {
debug!(?def_id);
- // Avoid cycle errors with generators.
+ // Avoid cycle errors with coroutines.
if def_id == self.def_id {
return ControlFlow::Continue(());
}
- // Consider any generic parameters used by any closures/generators as used in the
+ // Consider any generic parameters used by any closures/coroutines as used in the
// parent.
self.visit_child_body(def_id, args);
ControlFlow::Continue(())