rebased: convert rustc_monomorphize errors to SessionDiagnostic
This commit is contained in:
parent
4d45b0745a
commit
137f20c112
10 changed files with 170 additions and 41 deletions
10
Cargo.lock
10
Cargo.lock
|
@ -4253,8 +4253,10 @@ name = "rustc_monomorphize"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
|
@ -4995,9 +4997,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
|
|||
|
||||
[[package]]
|
||||
name = "snapbox"
|
||||
version = "0.3.3"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d199ccf8f606592df2d145db26f2aa45344e23c64b074cc5a4047f1d99b0f7"
|
||||
checksum = "767a1d5da232b6959cd1bd5c9e8db8a7cce09c3038e89deedb49a549a2aefd93"
|
||||
dependencies = [
|
||||
"concolor",
|
||||
"content_inspector",
|
||||
|
@ -5013,9 +5015,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "snapbox-macros"
|
||||
version = "0.3.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a253e6f894cfa440cba00600a249fa90869d8e0ec45ab274a456e043a0ce8f2"
|
||||
checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
|
|
19
compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
Normal file
19
compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
Normal file
|
@ -0,0 +1,19 @@
|
|||
monomorphize_recursion_limit =
|
||||
reached the recursion limit while instantiating `{$shrunk}`
|
||||
.note = `{$def_path_str}` defined here
|
||||
|
||||
monomorphize_written_to_path = the full type name has been written to '{$path}'
|
||||
|
||||
monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
|
||||
|
||||
monomorphize_consider_type_length_limit =
|
||||
consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
|
||||
|
||||
monomorphize_fatal_error = {$error_message}
|
||||
|
||||
monomorphize_unused_generic_params = item has unused generic parameters
|
||||
|
||||
monomorphize_large_assignments =
|
||||
moving {$size} bytes
|
||||
.label = value moved from here
|
||||
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
|
@ -39,6 +39,7 @@ fluent_messages! {
|
|||
expand => "../locales/en-US/expand.ftl",
|
||||
interface => "../locales/en-US/interface.ftl",
|
||||
lint => "../locales/en-US/lint.ftl",
|
||||
monomorphize => "../locales/en-US/monomorphize.ftl",
|
||||
parser => "../locales/en-US/parser.ftl",
|
||||
passes => "../locales/en-US/passes.ftl",
|
||||
plugin_impl => "../locales/en-US/plugin_impl.ftl",
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -207,6 +207,8 @@ use std::iter;
|
|||
use std::ops::Range;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::errors::{FatalError, LargeAssignmentsLint, RecursionLimit, 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,9 @@ 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(error_message) => {
|
||||
self.tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() });
|
||||
}
|
||||
};
|
||||
let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
|
||||
|
||||
|
|
81
compiler/rustc_monomorphize/src/errors.rs
Normal file
81
compiler/rustc_monomorphize/src/errors.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_macros::{LintDiagnostic, SessionDiagnostic};
|
||||
use rustc_session::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::fatal_error)]
|
||||
pub struct FatalError {
|
||||
pub error_message: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[diag(monomorphize::fatal_error)]
|
||||
pub struct SpanFatalError {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub error_message: 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,
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -108,6 +108,7 @@ use rustc_span::symbol::Symbol;
|
|||
|
||||
use crate::collector::InliningMap;
|
||||
use crate::collector::{self, MonoItemCollectionMode};
|
||||
use crate::errors::{FatalError, SpanFatalError};
|
||||
|
||||
pub struct PartitioningCx<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -149,7 +150,10 @@ fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
|
|||
|
||||
match strategy {
|
||||
"default" => Box::new(default::DefaultPartitioning),
|
||||
_ => tcx.sess.fatal("unknown partitioning strategy"),
|
||||
_ => {
|
||||
let error_message = "unknown partitioning strategy".to_string();
|
||||
tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,9 +338,9 @@ where
|
|||
let error_message = format!("symbol `{}` is already defined", sym1);
|
||||
|
||||
if let Some(span) = span {
|
||||
tcx.sess.span_fatal(span, &error_message)
|
||||
tcx.sess.emit_fatal(SpanFatalError { span, error_message: error_message.clone() });
|
||||
} else {
|
||||
tcx.sess.fatal(&error_message)
|
||||
tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,28 @@ 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));
|
||||
// 🤔 The docs say
|
||||
//
|
||||
// Any attribute applied to a Vec<T> will be repeated for each element of the vector.
|
||||
//
|
||||
// But they don't say what template variable to use to substitute each value into the message!?
|
||||
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.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6da726708a4406f31f996d813790818dce837161
|
||||
Subproject commit 9809f8ff33c2b998919fd0432c626f0f7323697a
|
Loading…
Add table
Reference in a new issue