summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_monomorphize/src/collector.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:03:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:03:36 +0000
commit17d40c6057c88f4c432b0d7bac88e1b84cb7e67f (patch)
tree3f66c4a5918660bb8a758ab6cda5ff8ee4f6cdcd /compiler/rustc_monomorphize/src/collector.rs
parentAdding upstream version 1.64.0+dfsg1. (diff)
downloadrustc-17d40c6057c88f4c432b0d7bac88e1b84cb7e67f.tar.xz
rustc-17d40c6057c88f4c432b0d7bac88e1b84cb7e67f.zip
Adding upstream version 1.65.0+dfsg1.upstream/1.65.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_monomorphize/src/collector.rs')
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs168
1 files changed, 79 insertions, 89 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 68b65658c..f1a25a60d 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -112,12 +112,6 @@
//! method in operand position, we treat it as a neighbor of the current
//! mono item. Calls are just a special case of that.
//!
-//! #### Closures
-//! In a way, closures are a simple case. Since every closure object needs to be
-//! constructed somewhere, we can reliably discover them by observing
-//! `RValue::Aggregate` expressions with `AggregateKind::Closure`. This is also
-//! true for closures inlined from other crates.
-//!
//! #### Drop glue
//! Drop glue mono items are introduced by MIR drop-statements. The
//! generated mono item will again have drop-glue item neighbors if the
@@ -128,7 +122,7 @@
//! #### Unsizing Casts
//! A subtle way of introducing neighbor edges is by casting to a trait object.
//! Since the resulting fat-pointer contains a reference to a vtable, we need to
-//! instantiate all object-save methods of the trait, as we need to store
+//! instantiate all object-safe methods of the trait, as we need to store
//! pointers to these functions even if they never get called anywhere. This can
//! be seen as a special case of taking a function reference.
//!
@@ -207,6 +201,8 @@ use std::iter;
use std::ops::Range;
use std::path::PathBuf;
+use crate::errors::{LargeAssignmentsLint, RecursionLimit, RequiresLangItem, TypeLengthLimit};
+
#[derive(PartialEq)]
pub enum MonoItemCollectionMode {
Eager,
@@ -417,7 +413,6 @@ fn collect_items_rec<'tcx>(
// We've been here already, no need to search again.
return;
}
- debug!("BEGIN collect_items_rec({})", starting_point.node);
let mut neighbors = MonoItems { compute_inlining: true, tcx, items: Vec::new() };
let recursion_depth_reset;
@@ -461,7 +456,7 @@ fn collect_items_rec<'tcx>(
recursion_depth_reset = None;
if let Ok(alloc) = tcx.eval_static_initializer(def_id) {
- for &id in alloc.inner().relocations().values() {
+ for &id in alloc.inner().provenance().values() {
collect_miri(tcx, id, &mut neighbors);
}
}
@@ -543,8 +538,6 @@ fn collect_items_rec<'tcx>(
if let Some((def_id, depth)) = recursion_depth_reset {
recursion_depths.insert(def_id, depth);
}
-
- debug!("END collect_items_rec({})", starting_point.node);
}
/// Format instance name that is already known to be too long for rustc.
@@ -604,17 +597,24 @@ fn check_recursion_limit<'tcx>(
// more than the recursion limit is assumed to be causing an
// infinite expansion.
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
+ let def_span = tcx.def_span(def_id);
+ let def_path_str = tcx.def_path_str(def_id);
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
- let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
- let mut err = tcx.sess.struct_span_fatal(span, &error);
- err.span_note(
- tcx.def_span(def_id),
- &format!("`{}` defined here", tcx.def_path_str(def_id)),
- );
- if let Some(path) = written_to_path {
- err.note(&format!("the full type name has been written to '{}'", path.display()));
- }
- err.emit()
+ let mut path = PathBuf::new();
+ let was_written = if written_to_path.is_some() {
+ path = written_to_path.unwrap();
+ Some(())
+ } else {
+ None
+ };
+ tcx.sess.emit_fatal(RecursionLimit {
+ span,
+ shrunk,
+ def_span,
+ def_path_str,
+ was_written,
+ path,
+ });
}
recursion_depths.insert(def_id, recursion_depth + 1);
@@ -642,16 +642,15 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
// Bail out in these cases to avoid that bad user experience.
if !tcx.type_length_limit().value_within_limit(type_length) {
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
- let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
- let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
- if let Some(path) = written_to_path {
- diag.note(&format!("the full type name has been written to '{}'", path.display()));
- }
- diag.help(&format!(
- "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
- type_length
- ));
- diag.emit()
+ let span = tcx.def_span(instance.def_id());
+ let mut path = PathBuf::new();
+ let was_written = if written_to_path.is_some() {
+ path = written_to_path.unwrap();
+ Some(())
+ } else {
+ None
+ };
+ tcx.sess.emit_fatal(TypeLengthLimit { span, shrunk, was_written, path, type_length });
}
}
@@ -690,7 +689,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
mir::CastKind::Pointer(PointerCast::Unsize),
ref operand,
target_ty,
- ) => {
+ )
+ | mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
let target_ty = self.monomorphize(target_ty);
let source_ty = operand.ty(self.body, self.tcx);
let source_ty = self.monomorphize(source_ty);
@@ -699,7 +699,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
// 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.
- if target_ty.is_trait() && !source_ty.is_trait() {
+ if (target_ty.is_trait() && !source_ty.is_trait())
+ || (target_ty.is_dyn_star() && !source_ty.is_dyn_star())
+ {
create_mono_items_for_vtable_methods(
self.tcx,
target_ty,
@@ -768,7 +770,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
ty::ConstKind::Unevaluated(ct) => {
debug!(?ct);
let param_env = ty::ParamEnv::reveal_all();
- match self.tcx.const_eval_resolve(param_env, ct, None) {
+ match self.tcx.const_eval_resolve(param_env, ct.expand(), None) {
// The `monomorphize` call should have evaluated that constant already.
Ok(val) => val,
Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
@@ -781,44 +783,22 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
}
_ => return,
},
- };
- collect_const_value(self.tcx, val, self.output);
- self.visit_ty(literal.ty(), TyContext::Location(location));
- }
-
- #[instrument(skip(self), level = "debug")]
- fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
- debug!("visiting const {:?} @ {:?}", constant, location);
-
- let substituted_constant = self.monomorphize(constant);
- let param_env = ty::ParamEnv::reveal_all();
-
- match substituted_constant.kind() {
- ty::ConstKind::Value(val) => {
- let const_val = self.tcx.valtree_to_const_val((constant.ty(), val));
- collect_const_value(self.tcx, const_val, self.output)
- }
- ty::ConstKind::Unevaluated(unevaluated) => {
- match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
+ mir::ConstantKind::Unevaluated(uv, _) => {
+ let param_env = ty::ParamEnv::reveal_all();
+ match self.tcx.const_eval_resolve(param_env, uv, None) {
// The `monomorphize` call should have evaluated that constant already.
- Ok(val) => span_bug!(
- self.body.source_info(location).span,
- "collection encountered the unevaluated constant {} which evaluated to {:?}",
- substituted_constant,
- val
- ),
- Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => {}
+ Ok(val) => val,
+ Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
Err(ErrorHandled::TooGeneric) => span_bug!(
self.body.source_info(location).span,
- "collection encountered polymorphic constant: {}",
- substituted_constant
+ "collection encountered polymorphic constant: {:?}",
+ literal
),
}
}
- _ => {}
- }
-
- self.super_const(constant);
+ };
+ collect_const_value(self.tcx, val, self.output);
+ MirVisitor::visit_ty(self, literal.ty(), TyContext::Location(location));
}
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
@@ -830,7 +810,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
mir::TerminatorKind::Call { ref func, .. } => {
let callee_ty = func.ty(self.body, tcx);
let callee_ty = self.monomorphize(callee_ty);
- visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output);
+ visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output)
}
mir::TerminatorKind::Drop { ref place, .. }
| mir::TerminatorKind::DropAndReplace { ref place, .. } => {
@@ -914,17 +894,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
// but correct span? This would make the lint at least accept crate-level lint attributes.
return;
};
- self.tcx.struct_span_lint_hir(
+ self.tcx.emit_spanned_lint(
LARGE_ASSIGNMENTS,
lint_root,
source_info.span,
- |lint| {
- let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
- err.span_label(source_info.span, "value moved from here");
- err.note(&format!(r#"The current maximum size is {}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`"#, limit.bytes()));
- err.emit();
+ LargeAssignmentsLint {
+ span: source_info.span,
+ size: layout.size.bytes(),
+ limit: limit.bytes(),
},
- );
+ )
}
}
}
@@ -1027,6 +1006,11 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
return false;
}
+ if let DefKind::Static(_) = tcx.def_kind(def_id) {
+ // We cannot monomorphize statics from upstream crates.
+ return false;
+ }
+
if !tcx.is_mir_available(def_id) {
bug!("no MIR available for {:?}", def_id);
}
@@ -1039,10 +1023,12 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
/// them.
///
/// For example, the source type might be `&SomeStruct` and the target type
-/// might be `&SomeTrait` in a cast like:
+/// might be `&dyn SomeTrait` in a cast like:
///
+/// ```rust,ignore (not real code)
/// let src: &SomeStruct = ...;
-/// let target = src as &SomeTrait;
+/// let target = src as &dyn SomeTrait;
+/// ```
///
/// Then the output of this function would be (SomeStruct, SomeTrait) since for
/// constructing the `target` fat-pointer we need the vtable for that pair.
@@ -1063,8 +1049,10 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
/// for the pair of `T` (which is a trait) and the concrete type that `T` was
/// originally coerced from:
///
+/// ```rust,ignore (not real code)
/// let src: &ComplexStruct<SomeStruct> = ...;
-/// let target = src as &ComplexStruct<SomeTrait>;
+/// let target = src as &ComplexStruct<dyn SomeTrait>;
+/// ```
///
/// Again, we want this `find_vtable_types_for_unsizing()` to provide the pair
/// `(SomeStruct, SomeTrait)`.
@@ -1105,6 +1093,9 @@ fn find_vtable_types_for_unsizing<'tcx>(
ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
}
+ // T as dyn* Trait
+ (_, &ty::Dynamic(_, _, ty::DynStar)) => ptr_vtable(source_ty, target_ty),
+
(&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => {
assert_eq!(source_adt_def, target_adt_def);
@@ -1132,23 +1123,18 @@ fn find_vtable_types_for_unsizing<'tcx>(
}
}
-#[instrument(skip(tcx), level = "debug")]
+#[instrument(skip(tcx), level = "debug", ret)]
fn create_fn_mono_item<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
source: Span,
) -> Spanned<MonoItem<'tcx>> {
- debug!("create_fn_mono_item(instance={})", instance);
-
let def_id = instance.def_id();
if tcx.sess.opts.unstable_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) {
crate::util::dump_closure_profile(tcx, instance);
}
- let respanned = respan(source, MonoItem::Fn(instance.polymorphize(tcx)));
- debug!(?respanned);
-
- respanned
+ respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
}
/// Creates a `MonoItem` for each method that is referenced by the vtable for
@@ -1293,7 +1279,7 @@ impl<'v> RootCollector<'_, 'v> {
#[instrument(skip(self), level = "debug")]
fn push_if_root(&mut self, def_id: LocalDefId) {
if self.is_root(def_id) {
- debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
+ debug!("found root");
let instance = Instance::mono(self.tcx, def_id.to_def_id());
self.output.push(create_fn_mono_item(self.tcx, instance, DUMMY_SP));
@@ -1306,13 +1292,17 @@ impl<'v> RootCollector<'_, 'v> {
/// the return type of `main`. This is not needed when
/// the user writes their own `start` manually.
fn push_extra_entry_roots(&mut self) {
- let Some((main_def_id, EntryFnType::Main)) = self.entry_fn else {
+ let Some((main_def_id, EntryFnType::Main { .. })) = self.entry_fn else {
return;
};
let start_def_id = match self.tcx.lang_items().require(LangItem::Start) {
Ok(s) => s,
- Err(err) => self.tcx.sess.fatal(&err),
+ Err(lang_item_err) => {
+ self.tcx
+ .sess
+ .emit_fatal(RequiresLangItem { lang_item: lang_item_err.0.name().to_string() });
+ }
};
let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
@@ -1415,7 +1405,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIte
}
GlobalAlloc::Memory(alloc) => {
trace!("collecting {:?} with {:#?}", alloc_id, alloc);
- for &inner in alloc.inner().relocations().values() {
+ for &inner in alloc.inner().provenance().values() {
rustc_data_structures::stack::ensure_sufficient_stack(|| {
collect_miri(tcx, inner, output);
});
@@ -1454,7 +1444,7 @@ fn collect_const_value<'tcx>(
match value {
ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => collect_miri(tcx, ptr.provenance, output),
ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
- for &id in alloc.inner().relocations().values() {
+ for &id in alloc.inner().provenance().values() {
collect_miri(tcx, id, output);
}
}