summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_monomorphize
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml5
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs202
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs84
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs6
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs6
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs15
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs64
-rw-r--r--compiler/rustc_monomorphize/src/util.rs2
8 files changed, 236 insertions, 148 deletions
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 41ba4d4b6..6ee5330b6 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -4,14 +4,15 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
tracing = "0.1"
rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
+rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 68b65658c..a71218e69 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)`.
@@ -1079,7 +1067,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
let param_env = ty::ParamEnv::reveal_all();
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
- if ty.is_sized(tcx.at(DUMMY_SP), param_env) {
+ if ty.is_sized(tcx, param_env) {
return false;
}
let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);
@@ -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
@@ -1206,7 +1192,7 @@ struct RootCollector<'a, 'tcx> {
impl<'v> RootCollector<'_, 'v> {
fn process_item(&mut self, id: hir::ItemId) {
- match self.tcx.def_kind(id.def_id) {
+ match self.tcx.def_kind(id.owner_id) {
DefKind::Enum | DefKind::Struct | DefKind::Union => {
let item = self.tcx.hir().item(id);
match item.kind {
@@ -1217,12 +1203,14 @@ impl<'v> RootCollector<'_, 'v> {
if self.mode == MonoItemCollectionMode::Eager {
debug!(
"RootCollector: ADT drop-glue for {}",
- self.tcx.def_path_str(item.def_id.to_def_id())
+ self.tcx.def_path_str(item.owner_id.to_def_id())
);
- let ty =
- Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
- .ty(self.tcx, ty::ParamEnv::reveal_all());
+ let ty = Instance::new(
+ item.owner_id.to_def_id(),
+ InternalSubsts::empty(),
+ )
+ .ty(self.tcx, ty::ParamEnv::reveal_all());
visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
}
}
@@ -1233,23 +1221,23 @@ impl<'v> RootCollector<'_, 'v> {
DefKind::GlobalAsm => {
debug!(
"RootCollector: ItemKind::GlobalAsm({})",
- self.tcx.def_path_str(id.def_id.to_def_id())
+ self.tcx.def_path_str(id.owner_id.to_def_id())
);
self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
}
DefKind::Static(..) => {
debug!(
"RootCollector: ItemKind::Static({})",
- self.tcx.def_path_str(id.def_id.to_def_id())
+ self.tcx.def_path_str(id.owner_id.to_def_id())
);
- self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id())));
+ self.output.push(dummy_spanned(MonoItem::Static(id.owner_id.to_def_id())));
}
DefKind::Const => {
// const items only generate mono items if they are
// actually used somewhere. Just declaring them is insufficient.
// but even just declaring them must collect the items they refer to
- if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) {
+ if let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id()) {
collect_const_value(self.tcx, val, &mut self.output);
}
}
@@ -1260,15 +1248,15 @@ impl<'v> RootCollector<'_, 'v> {
}
}
DefKind::Fn => {
- self.push_if_root(id.def_id);
+ self.push_if_root(id.owner_id.def_id);
}
_ => {}
}
}
fn process_impl_item(&mut self, id: hir::ImplItemId) {
- if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) {
- self.push_if_root(id.def_id);
+ if matches!(self.tcx.def_kind(id.owner_id), DefKind::AssocFn) {
+ self.push_if_root(id.owner_id.def_id);
}
}
@@ -1293,7 +1281,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 +1294,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();
@@ -1362,13 +1354,13 @@ fn create_mono_items_for_default_impls<'tcx>(
debug!(
"create_mono_items_for_default_impls(item={})",
- tcx.def_path_str(item.def_id.to_def_id())
+ tcx.def_path_str(item.owner_id.to_def_id())
);
- if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
+ if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
let param_env = ty::ParamEnv::reveal_all();
let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
- let overridden_methods = tcx.impl_item_implementor_ids(item.def_id);
+ let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
for method in tcx.provided_trait_methods(trait_ref.def_id) {
if overridden_methods.contains_key(&method.def_id) {
continue;
@@ -1415,7 +1407,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 +1446,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);
}
}
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
new file mode 100644
index 000000000..ce097b8d8
--- /dev/null
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -0,0 +1,84 @@
+use std::path::PathBuf;
+
+use rustc_errors::ErrorGuaranteed;
+use rustc_errors::IntoDiagnostic;
+use rustc_macros::{Diagnostic, LintDiagnostic};
+use rustc_span::Span;
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_recursion_limit)]
+pub struct RecursionLimit {
+ #[primary_span]
+ pub span: Span,
+ pub shrunk: String,
+ #[note]
+ pub def_span: Span,
+ pub def_path_str: String,
+ #[note(monomorphize_written_to_path)]
+ pub was_written: Option<()>,
+ pub path: PathBuf,
+}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_type_length_limit)]
+#[help(monomorphize_consider_type_length_limit)]
+pub struct TypeLengthLimit {
+ #[primary_span]
+ pub span: Span,
+ pub shrunk: String,
+ #[note(monomorphize_written_to_path)]
+ pub was_written: Option<()>,
+ pub path: PathBuf,
+ pub type_length: usize,
+}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_requires_lang_item)]
+pub struct RequiresLangItem {
+ pub lang_item: String,
+}
+
+pub struct UnusedGenericParams {
+ pub span: Span,
+ pub param_spans: Vec<Span>,
+ pub param_names: Vec<String>,
+}
+
+impl IntoDiagnostic<'_> for UnusedGenericParams {
+ fn into_diagnostic(
+ self,
+ handler: &'_ rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_err(rustc_errors::fluent::monomorphize_unused_generic_params);
+ diag.set_span(self.span);
+ for (span, name) in self.param_spans.into_iter().zip(self.param_names) {
+ // FIXME: I can figure out how to do a label with a fluent string with a fixed message,
+ // or a label with a dynamic value in a hard-coded string, but I haven't figured out
+ // how to combine the two. 😢
+ diag.span_label(span, format!("generic parameter `{}` is unused", name));
+ }
+ diag
+ }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(monomorphize_large_assignments)]
+#[note]
+pub struct LargeAssignmentsLint {
+ #[label]
+ pub span: Span,
+ pub size: u64,
+ pub limit: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_unknown_partition_strategy)]
+pub struct UnknownPartitionStrategy;
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_symbol_already_defined)]
+pub struct SymbolAlreadyDefined {
+ #[primary_span]
+ pub span: Option<Span>,
+ pub symbol: String,
+}
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index ef4560b5e..42781bd25 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,8 +1,9 @@
#![feature(array_windows)]
#![feature(control_flow_enum)]
-#![feature(let_else)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate tracing;
@@ -16,6 +17,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
mod collector;
+mod errors;
mod partitioning;
mod polymorphize;
mod util;
@@ -32,7 +34,7 @@ fn custom_coerce_unsize_info<'tcx>(
substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
});
- match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
+ match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
impl_def_id,
..
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 15276569c..29009c480 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -319,7 +319,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
Some(def_id)
}
MonoItem::Static(def_id) => Some(def_id),
- MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.to_def_id()),
+ MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.to_def_id()),
}
}
@@ -411,9 +411,9 @@ fn mono_item_visibility<'tcx>(
};
}
MonoItem::GlobalAsm(item_id) => {
- return if tcx.is_reachable_non_generic(item_id.def_id) {
+ return if tcx.is_reachable_non_generic(item_id.owner_id) {
*can_be_internalized = false;
- default_visibility(tcx, item_id.def_id.to_def_id(), false)
+ default_visibility(tcx, item_id.owner_id.to_def_id(), false)
} else {
Visibility::Hidden
};
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index ff2d38693..932edc667 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -108,6 +108,7 @@ use rustc_span::symbol::Symbol;
use crate::collector::InliningMap;
use crate::collector::{self, MonoItemCollectionMode};
+use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
pub struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -149,7 +150,9 @@ fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
match strategy {
"default" => Box::new(default::DefaultPartitioning),
- _ => tcx.sess.fatal("unknown partitioning strategy"),
+ _ => {
+ tcx.sess.emit_fatal(UnknownPartitionStrategy);
+ }
}
}
@@ -331,13 +334,7 @@ where
(span1, span2) => span1.or(span2),
};
- let error_message = format!("symbol `{}` is already defined", sym1);
-
- if let Some(span) = span {
- tcx.sess.span_fatal(span, &error_message)
- } else {
- tcx.sess.fatal(&error_message)
- }
+ tcx.sess.emit_fatal(SymbolAlreadyDefined { span, symbol: sym1.to_string() });
}
}
}
@@ -481,7 +478,7 @@ fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSe
continue;
}
let body = tcx.instance_mir(instance.def);
- for block in body.basic_blocks() {
+ 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;
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 394843e51..650076c22 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -8,8 +8,9 @@
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{
+ self,
visit::{TyContext, Visitor},
- Local, LocalDecl, Location,
+ Constant, ConstantKind, Local, LocalDecl, Location,
};
use rustc_middle::ty::{
self,
@@ -22,6 +23,8 @@ use rustc_span::symbol::sym;
use std::convert::TryInto;
use std::ops::ControlFlow;
+use crate::errors::UnusedGenericParams;
+
/// Provide implementations of queries relating to polymorphization analysis.
pub fn provide(providers: &mut Providers) {
providers.unused_generic_params = unused_generic_params;
@@ -31,7 +34,6 @@ pub fn provide(providers: &mut Providers) {
///
/// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all
/// parameters are used).
-#[instrument(level = "debug", skip(tcx))]
fn unused_generic_params<'tcx>(
tcx: TyCtxt<'tcx>,
instance: ty::InstanceDef<'tcx>,
@@ -169,6 +171,7 @@ fn mark_used_by_default_parameters<'tcx>(
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
+ | DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
@@ -206,22 +209,23 @@ fn emit_unused_generic_params_error<'tcx>(
_ => tcx.def_span(def_id),
};
- let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters");
-
+ let mut param_spans = Vec::new();
+ let mut param_names = Vec::new();
let mut next_generics = Some(generics);
while let Some(generics) = next_generics {
for param in &generics.params {
if unused_parameters.contains(param.index).unwrap_or(false) {
debug!(?param);
let def_span = tcx.def_span(param.def_id);
- err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name));
+ param_spans.push(def_span);
+ param_names.push(param.name.to_string());
}
}
next_generics = generics.parent.map(|did| tcx.generics_of(did));
}
- err.emit();
+ tcx.sess.emit_err(UnusedGenericParams { span: fn_span, param_spans, param_names });
}
/// Visitor used to aggregate generic parameter uses.
@@ -267,8 +271,27 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.super_local_decl(local, local_decl);
}
- fn visit_const(&mut self, c: Const<'tcx>, _: Location) {
- c.visit_with(self);
+ fn visit_constant(&mut self, ct: &Constant<'tcx>, location: Location) {
+ match ct.literal {
+ ConstantKind::Ty(c) => {
+ c.visit_with(self);
+ }
+ ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted }, ty) => {
+ // Avoid considering `T` unused when constants are of the form:
+ // `<Self as Foo<T>>::foo::promoted[p]`
+ if let Some(p) = promoted {
+ if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self {
+ // If there is a promoted, don't look at the substs - since it will always contain
+ // the generic parameters, instead, traverse the promoted MIR.
+ let promoted = self.tcx.promoted_mir(def.did);
+ self.visit_body(&promoted[p]);
+ }
+ }
+
+ Visitor::visit_ty(self, ty, TyContext::Location(location));
+ }
+ ConstantKind::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)),
+ }
}
fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
@@ -279,7 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !c.has_param_types_or_consts() {
+ if !c.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@@ -289,21 +312,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE
}
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
- // Avoid considering `T` unused when constants are of the form:
- // `<Self as Foo<T>>::foo::promoted[p]`
- if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
- {
- // If there is a promoted, don't look at the substs - since it will always contain
- // the generic parameters, instead, traverse the promoted MIR.
- let promoted = self.tcx.promoted_mir(def.did);
- self.visit_body(&promoted[p]);
- ControlFlow::CONTINUE
- }
- ty::ConstKind::Unevaluated(uv)
- if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) =>
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
+ if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
{
- self.visit_child_body(uv.def.did, uv.substs);
+ self.visit_child_body(def.did, substs);
ControlFlow::CONTINUE
}
_ => c.super_visit_with(self),
@@ -312,7 +324,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.has_param_types_or_consts() {
+ if !ty.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@@ -349,7 +361,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !c.has_param_types_or_consts() {
+ if !c.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@@ -367,7 +379,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.has_param_types_or_consts() {
+ if !ty.has_non_region_param() {
return ControlFlow::CONTINUE;
}
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 847e64dc2..6a4d2df1e 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -13,7 +13,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
.append(true)
.open(&format!("closure_profile_{}.csv", std::process::id()))
else {
- eprintln!("Cound't open file for writing closure profile");
+ eprintln!("Couldn't open file for writing closure profile");
return;
};