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:
commit
6c4bda6de4
@ -3905,8 +3905,10 @@ name = "rustc_monomorphize"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
|
"rustc_errors",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
|
"rustc_macros",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
|
@ -925,8 +925,11 @@ pub(crate) fn codegen_panic_inner<'tcx>(
|
|||||||
args: &[Value],
|
args: &[Value],
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
let def_id =
|
let def_id = fx
|
||||||
fx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| fx.tcx.sess.span_fatal(span, &s));
|
.tcx
|
||||||
|
.lang_items()
|
||||||
|
.require(lang_item)
|
||||||
|
.unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string()));
|
||||||
|
|
||||||
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
|
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
|
||||||
let symbol_name = fx.tcx.symbol_name(instance).name;
|
let symbol_name = fx.tcx.symbol_name(instance).name;
|
||||||
|
26
compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
Normal file
26
compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
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_unknown_partition_strategy = unknown partitioning strategy
|
||||||
|
|
||||||
|
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
|
||||||
|
|
||||||
|
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 = "..."]`
|
||||||
|
|
||||||
|
monomorphize_requires_lang_item =
|
||||||
|
requires `{$lang_item}` lang_item
|
@ -44,6 +44,7 @@ fluent_messages! {
|
|||||||
interface => "../locales/en-US/interface.ftl",
|
interface => "../locales/en-US/interface.ftl",
|
||||||
infer => "../locales/en-US/infer.ftl",
|
infer => "../locales/en-US/infer.ftl",
|
||||||
lint => "../locales/en-US/lint.ftl",
|
lint => "../locales/en-US/lint.ftl",
|
||||||
|
monomorphize => "../locales/en-US/monomorphize.ftl",
|
||||||
parser => "../locales/en-US/parser.ftl",
|
parser => "../locales/en-US/parser.ftl",
|
||||||
passes => "../locales/en-US/passes.ftl",
|
passes => "../locales/en-US/passes.ftl",
|
||||||
plugin_impl => "../locales/en-US/plugin_impl.ftl",
|
plugin_impl => "../locales/en-US/plugin_impl.ftl",
|
||||||
|
10
compiler/rustc_hir/src/errors.rs
Normal file
10
compiler/rustc_hir/src/errors.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use crate::LangItem;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||||
|
pub struct LangItemError(pub LangItem);
|
||||||
|
|
||||||
|
impl ToString for LangItemError {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("requires `{}` lang_item", self.0.name())
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@
|
|||||||
//! * Functions called by the compiler itself.
|
//! * Functions called by the compiler itself.
|
||||||
|
|
||||||
use crate::def_id::DefId;
|
use crate::def_id::DefId;
|
||||||
|
use crate::errors::LangItemError;
|
||||||
use crate::{MethodKind, Target};
|
use crate::{MethodKind, Target};
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
@ -115,9 +116,9 @@ macro_rules! language_item_table {
|
|||||||
|
|
||||||
/// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
|
/// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
|
||||||
/// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
|
/// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
|
||||||
/// returns an error message as a string.
|
/// returns an error encapsulating the `LangItem`.
|
||||||
pub fn require(&self, it: LangItem) -> Result<DefId, String> {
|
pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
|
||||||
self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
|
self.items[it as usize].ok_or_else(|| LangItemError(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [`DefId`]s of all lang items in a group.
|
/// Returns the [`DefId`]s of all lang items in a group.
|
||||||
|
@ -27,6 +27,7 @@ pub mod def;
|
|||||||
pub mod def_path_hash_map;
|
pub mod def_path_hash_map;
|
||||||
pub mod definitions;
|
pub mod definitions;
|
||||||
pub mod diagnostic_items;
|
pub mod diagnostic_items;
|
||||||
|
pub mod errors;
|
||||||
pub use rustc_span::def_id;
|
pub use rustc_span::def_id;
|
||||||
mod hir;
|
mod hir;
|
||||||
pub mod hir_id;
|
pub mod hir_id;
|
||||||
|
@ -18,11 +18,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
/// Returns the `DefId` for a given `LangItem`.
|
/// Returns the `DefId` for a given `LangItem`.
|
||||||
/// If not found, fatally aborts compilation.
|
/// If not found, fatally aborts compilation.
|
||||||
pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
|
pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
|
||||||
self.lang_items().require(lang_item).unwrap_or_else(|msg| {
|
self.lang_items().require(lang_item).unwrap_or_else(|err| {
|
||||||
if let Some(span) = span {
|
if let Some(span) = span {
|
||||||
self.sess.span_fatal(span, &msg)
|
self.sess.span_fatal(span, err.to_string())
|
||||||
} else {
|
} else {
|
||||||
self.sess.fatal(&msg)
|
self.sess.fatal(err.to_string())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,10 @@ doctest = false
|
|||||||
smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
|
smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
|
rustc_errors = { path = "../rustc_errors" }
|
||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
rustc_index = { path = "../rustc_index" }
|
rustc_index = { path = "../rustc_index" }
|
||||||
|
rustc_macros = { path = "../rustc_macros" }
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
rustc_session = { path = "../rustc_session" }
|
rustc_session = { path = "../rustc_session" }
|
||||||
rustc_span = { path = "../rustc_span" }
|
rustc_span = { path = "../rustc_span" }
|
||||||
|
@ -207,6 +207,8 @@ use std::iter;
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::errors::{LargeAssignmentsLint, RecursionLimit, RequiresLangItem, TypeLengthLimit};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum MonoItemCollectionMode {
|
pub enum MonoItemCollectionMode {
|
||||||
Eager,
|
Eager,
|
||||||
@ -604,17 +606,24 @@ fn check_recursion_limit<'tcx>(
|
|||||||
// more than the recursion limit is assumed to be causing an
|
// more than the recursion limit is assumed to be causing an
|
||||||
// infinite expansion.
|
// infinite expansion.
|
||||||
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
|
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 (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
|
||||||
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
|
let mut path = PathBuf::new();
|
||||||
let mut err = tcx.sess.struct_span_fatal(span, &error);
|
let was_written = if written_to_path.is_some() {
|
||||||
err.span_note(
|
path = written_to_path.unwrap();
|
||||||
tcx.def_span(def_id),
|
Some(())
|
||||||
&format!("`{}` defined here", tcx.def_path_str(def_id)),
|
} else {
|
||||||
);
|
None
|
||||||
if let Some(path) = written_to_path {
|
};
|
||||||
err.note(&format!("the full type name has been written to '{}'", path.display()));
|
tcx.sess.emit_fatal(RecursionLimit {
|
||||||
}
|
span,
|
||||||
err.emit()
|
shrunk,
|
||||||
|
def_span,
|
||||||
|
def_path_str,
|
||||||
|
was_written,
|
||||||
|
path,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
recursion_depths.insert(def_id, recursion_depth + 1);
|
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.
|
// Bail out in these cases to avoid that bad user experience.
|
||||||
if !tcx.type_length_limit().value_within_limit(type_length) {
|
if !tcx.type_length_limit().value_within_limit(type_length) {
|
||||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
|
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
|
||||||
let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
|
let span = tcx.def_span(instance.def_id());
|
||||||
let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
|
let mut path = PathBuf::new();
|
||||||
if let Some(path) = written_to_path {
|
let was_written = if written_to_path.is_some() {
|
||||||
diag.note(&format!("the full type name has been written to '{}'", path.display()));
|
path = written_to_path.unwrap();
|
||||||
}
|
Some(())
|
||||||
diag.help(&format!(
|
} else {
|
||||||
"consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
|
None
|
||||||
type_length
|
};
|
||||||
));
|
tcx.sess.emit_fatal(TypeLengthLimit { span, shrunk, was_written, path, type_length });
|
||||||
diag.emit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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.
|
// but correct span? This would make the lint at least accept crate-level lint attributes.
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.emit_spanned_lint(
|
||||||
LARGE_ASSIGNMENTS,
|
LARGE_ASSIGNMENTS,
|
||||||
lint_root,
|
lint_root,
|
||||||
source_info.span,
|
source_info.span,
|
||||||
|lint| {
|
LargeAssignmentsLint {
|
||||||
let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes()));
|
span: source_info.span,
|
||||||
err.span_label(source_info.span, "value moved from here");
|
size: layout.size.bytes(),
|
||||||
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()));
|
limit: limit.bytes(),
|
||||||
err.emit();
|
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1321,7 +1328,11 @@ impl<'v> RootCollector<'_, 'v> {
|
|||||||
|
|
||||||
let start_def_id = match self.tcx.lang_items().require(LangItem::Start) {
|
let start_def_id = match self.tcx.lang_items().require(LangItem::Start) {
|
||||||
Ok(s) => s,
|
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();
|
let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
|
||||||
|
|
||||||
|
84
compiler/rustc_monomorphize/src/errors.rs
Normal file
84
compiler/rustc_monomorphize/src/errors.rs
Normal 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,
|
||||||
|
}
|
@ -3,6 +3,8 @@
|
|||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate tracing;
|
extern crate tracing;
|
||||||
@ -16,6 +18,7 @@ use rustc_middle::ty::query::Providers;
|
|||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
mod collector;
|
mod collector;
|
||||||
|
mod errors;
|
||||||
mod partitioning;
|
mod partitioning;
|
||||||
mod polymorphize;
|
mod polymorphize;
|
||||||
mod util;
|
mod util;
|
||||||
|
@ -108,6 +108,7 @@ use rustc_span::symbol::Symbol;
|
|||||||
|
|
||||||
use crate::collector::InliningMap;
|
use crate::collector::InliningMap;
|
||||||
use crate::collector::{self, MonoItemCollectionMode};
|
use crate::collector::{self, MonoItemCollectionMode};
|
||||||
|
use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
|
||||||
|
|
||||||
pub struct PartitioningCx<'a, 'tcx> {
|
pub struct PartitioningCx<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
@ -149,7 +150,9 @@ fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
|
|||||||
|
|
||||||
match strategy {
|
match strategy {
|
||||||
"default" => Box::new(default::DefaultPartitioning),
|
"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),
|
(span1, span2) => span1.or(span2),
|
||||||
};
|
};
|
||||||
|
|
||||||
let error_message = format!("symbol `{}` is already defined", sym1);
|
tcx.sess.emit_fatal(SymbolAlreadyDefined { span, symbol: sym1.to_string() });
|
||||||
|
|
||||||
if let Some(span) = span {
|
|
||||||
tcx.sess.span_fatal(span, &error_message)
|
|
||||||
} else {
|
|
||||||
tcx.sess.fatal(&error_message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ use rustc_span::symbol::sym;
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
use crate::errors::UnusedGenericParams;
|
||||||
|
|
||||||
/// Provide implementations of queries relating to polymorphization analysis.
|
/// Provide implementations of queries relating to polymorphization analysis.
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
providers.unused_generic_params = unused_generic_params;
|
providers.unused_generic_params = unused_generic_params;
|
||||||
@ -206,22 +208,23 @@ fn emit_unused_generic_params_error<'tcx>(
|
|||||||
_ => tcx.def_span(def_id),
|
_ => 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);
|
let mut next_generics = Some(generics);
|
||||||
while let Some(generics) = next_generics {
|
while let Some(generics) = next_generics {
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
if unused_parameters.contains(param.index).unwrap_or(false) {
|
if unused_parameters.contains(param.index).unwrap_or(false) {
|
||||||
debug!(?param);
|
debug!(?param);
|
||||||
let def_span = tcx.def_span(param.def_id);
|
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));
|
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.
|
/// Visitor used to aggregate generic parameter uses.
|
||||||
|
@ -359,7 +359,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
|||||||
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
|
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
|
||||||
|
|
||||||
let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
|
let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
|
||||||
tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
|
tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
|
||||||
});
|
});
|
||||||
|
|
||||||
let source = tcx.type_of(impl_did);
|
let source = tcx.type_of(impl_did);
|
||||||
|
@ -4,8 +4,8 @@ error: reached the type-length limit while instantiating `std::mem::drop::<Optio
|
|||||||
LL | pub fn drop<T>(_x: T) {}
|
LL | pub fn drop<T>(_x: T) {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
|
||||||
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
||||||
|
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
||||||
|
|
||||||
error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)`
|
error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)`
|
||||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||||
@ -13,8 +13,8 @@ error: reached the type-length limit while instantiating `<[closure@std::rt::lan
|
|||||||
LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
|
||||||
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
= help: consider adding a `#![type_length_limit="8"]` attribute to your crate
|
||||||
|
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user