From 17d40c6057c88f4c432b0d7bac88e1b84cb7e67f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:03:36 +0200 Subject: Adding upstream version 1.65.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_monomorphize/Cargo.toml | 4 +- compiler/rustc_monomorphize/src/collector.rs | 168 ++++++++++----------- compiler/rustc_monomorphize/src/errors.rs | 85 +++++++++++ compiler/rustc_monomorphize/src/lib.rs | 7 +- .../rustc_monomorphize/src/partitioning/mod.rs | 15 +- compiler/rustc_monomorphize/src/polymorphize.rs | 55 +++++-- compiler/rustc_monomorphize/src/util.rs | 2 +- 7 files changed, 219 insertions(+), 117 deletions(-) create mode 100644 compiler/rustc_monomorphize/src/errors.rs (limited to 'compiler/rustc_monomorphize') diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 41ba4d4b6..59ca04ec8 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -7,11 +7,13 @@ edition = "2021" 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..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 = ...; -/// let target = src as &ComplexStruct; +/// let target = src as &ComplexStruct; +/// ``` /// /// 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> { - 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); } } diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs new file mode 100644 index 000000000..d5f05e790 --- /dev/null +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -0,0 +1,85 @@ +use std::path::PathBuf; + +use rustc_errors::ErrorGuaranteed; +use rustc_macros::{LintDiagnostic, SessionDiagnostic}; +use rustc_session::SessionDiagnostic; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[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(SessionDiagnostic)] +#[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(SessionDiagnostic)] +#[diag(monomorphize::requires_lang_item)] +pub struct RequiresLangItem { + pub lang_item: String, +} + +pub struct UnusedGenericParams { + pub span: Span, + pub param_spans: Vec, + pub param_names: Vec, +} + +impl SessionDiagnostic<'_> 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(SessionDiagnostic)] +#[diag(monomorphize::unknown_partition_strategy)] +pub struct UnknownPartitionStrategy; + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::symbol_already_defined)] +pub struct SymbolAlreadyDefined { + #[primary_span] + pub span: Option, + pub symbol: String, +} diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index ef4560b5e..ba6ce9fd4 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,8 +1,10 @@ #![feature(array_windows)] #![feature(control_flow_enum)] -#![feature(let_else)] +#![cfg_attr(bootstrap, 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 +18,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 +35,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/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> { 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..71cab0232 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -9,7 +9,7 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext}; use rustc_index::bit_set::FiniteBitSet; use rustc_middle::mir::{ visit::{TyContext, Visitor}, - Local, LocalDecl, Location, + Constant, ConstantKind, Local, LocalDecl, Location, }; use rustc_middle::ty::{ self, @@ -22,6 +22,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 +33,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 +170,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm @@ -206,22 +208,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 +270,15 @@ 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::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => { + Visitor::visit_ty(self, ty, TyContext::Location(location)) + } + } } fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) { @@ -289,7 +299,26 @@ 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)}) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) => + { + assert_eq!(promoted, ()); + + self.visit_child_body(def.did, substs); + ControlFlow::CONTINUE + } + _ => c.super_visit_with(self), + } + } + + fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow { + if !constant.has_param_types_or_consts() { + return ControlFlow::CONTINUE; + } + + match constant { + ConstantKind::Ty(ct) => ct.visit_with(self), + ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => @@ -300,13 +329,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.visit_body(&promoted[p]); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(uv) - if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) => - { - self.visit_child_body(uv.def.did, uv.substs); - ControlFlow::CONTINUE + ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => { + constant.super_visit_with(self) } - _ => c.super_visit_with(self), } } 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; }; -- cgit v1.2.3