about summary refs log tree commit diff
path: root/compiler/rustc_monomorphize/src
diff options
context:
space:
mode:
authorMatthew Kelly <matthew.kelly2@gmail.com>2022-08-31 19:39:39 -0400
committerMatthew Kelly <matthew.kelly2@gmail.com>2022-08-31 19:39:39 -0400
commiteda2a401457ba645a32bdc5b9e7e90214e3e4e24 (patch)
tree76c4a12cb26666f03aa37a81abe27782def16f1d /compiler/rustc_monomorphize/src
parent4a443dfb8227d407ff3f0542cb6e688833708ba9 (diff)
parent9243168fa5615ec8ebe9164c6bc2fdcccffd08b6 (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.rs85
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs84
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs3
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs15
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs11
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.