diff options
| author | Matthew Kelly <matthew.kelly2@gmail.com> | 2022-08-31 19:39:39 -0400 |
|---|---|---|
| committer | Matthew Kelly <matthew.kelly2@gmail.com> | 2022-08-31 19:39:39 -0400 |
| commit | eda2a401457ba645a32bdc5b9e7e90214e3e4e24 (patch) | |
| tree | 76c4a12cb26666f03aa37a81abe27782def16f1d /compiler/rustc_monomorphize/src | |
| parent | 4a443dfb8227d407ff3f0542cb6e688833708ba9 (diff) | |
| parent | 9243168fa5615ec8ebe9164c6bc2fdcccffd08b6 (diff) | |
Merge remote-tracking branch 'origin/master' into mpk/add-long-error-message-for-E0311
Diffstat (limited to 'compiler/rustc_monomorphize/src')
| -rw-r--r-- | compiler/rustc_monomorphize/src/collector.rs | 85 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/errors.rs | 84 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/lib.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/partitioning/mod.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/polymorphize.rs | 11 |
5 files changed, 150 insertions, 48 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 96bbf5802e7..170616d4b42 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -128,7 +128,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 +207,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, @@ -461,7 +463,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); } } @@ -604,17 +606,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 +651,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 }); } } @@ -914,17 +922,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(), }, - ); + ) } } } @@ -1044,10 +1051,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. @@ -1068,8 +1077,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)`. @@ -1317,7 +1328,11 @@ impl<'v> RootCollector<'_, 'v> { 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(); @@ -1420,7 +1435,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); }); @@ -1459,7 +1474,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 00000000000..77b6cfa1f69 --- /dev/null +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -0,0 +1,84 @@ +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<Span>, + pub param_names: Vec<String>, +} + +impl SessionDiagnostic<'_> for UnusedGenericParams { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.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<Span>, + pub symbol: String, +} diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index ef4560b5ec4..d64de44705b 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -3,6 +3,8 @@ #![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; diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index ff2d3869328..932edc6675f 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 394843e510d..6e4ab2a35c3 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -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; @@ -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. |
