1
Fork 0

Rollup merge of #100730 - CleanCut:diagnostics-rustc_monomorphize, r=davidtwco

Migrate rustc_monomorphize to use SessionDiagnostic

### Description

- Migrates diagnostics in `rustc_monomorphize` to use `SessionDiagnostic`
- Adds an `impl IntoDiagnosticArg for PathBuf`

### TODO / Help!
- [x] I'm having trouble figuring out how to apply an optional note. 😕  Help!?
  - Resolved. It was bad docs. Fixed in https://github.com/rust-lang/rustc-dev-guide/pull/1437/files
- [x] `errors:RecursionLimit` should be `#[fatal ...]`, but that doesn't exist so it's `#[error ...]` at the moment.
  - Maybe I can switch after this is merged in? --> https://github.com/rust-lang/rust/pull/100694
  - Or maybe I need to manually implement `SessionDiagnostic` instead of deriving it?
- [x] How does one go about converting an error inside of [a call to struct_span_lint_hir](8064a49508/compiler/rustc_monomorphize/src/collector.rs (L917-L927))?
- [x] ~What placeholder do you use in the fluent template to refer to the value in a vector? It seems like [this code](0b79f758c9/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs (L83-L114)) ought to have the answer (or something near it)...but I can't figure it out.~ You can't. Punted.
This commit is contained in:
Ralf Jung 2022-08-31 14:29:51 +02:00 committed by GitHub
commit 6c4bda6de4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 196 additions and 52 deletions

View file

@ -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,
@ -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(),
},
);
)
}
}
}
@ -1321,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();

View file

@ -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,
}

View file

@ -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;

View file

@ -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() });
}
}
}

View file

@ -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.