Auto merge of #136433 - matthiaskrgr:rollup-co27itw, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #133266 (ci: fix explanation why LLVM download is disabled for windows-gnu) - #136133 (Fix sentence in process::abort) - #136279 (Rename `tcx.ensure()` to `tcx.ensure_ok()`, and improve the associated docs) - #136328 (Rework "long type names" printing logic) - #136358 (`#[optimize(none)]` implies `#[inline(never)]`) - #136368 (Make comma separated lists of anything easier to make for errors) - #136412 (Tweak fn pointer suggestion span) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
e1f09207fb
95 changed files with 726 additions and 1132 deletions
|
|
@ -418,10 +418,10 @@ fn compute_hir_hash(
|
|||
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
|
||||
let sess = tcx.sess;
|
||||
// Queries that borrow `resolver_for_lowering`.
|
||||
tcx.ensure_with_value().output_filenames(());
|
||||
tcx.ensure_with_value().early_lint_checks(());
|
||||
tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE);
|
||||
tcx.ensure_with_value().get_lang_items(());
|
||||
tcx.ensure_done().output_filenames(());
|
||||
tcx.ensure_done().early_lint_checks(());
|
||||
tcx.ensure_done().debugger_visualizers(LOCAL_CRATE);
|
||||
tcx.ensure_done().get_lang_items(());
|
||||
let (mut resolver, krate) = tcx.resolver_for_lowering().steal();
|
||||
|
||||
let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
|
||||
|
|
|
|||
|
|
@ -92,9 +92,6 @@ borrowck_lifetime_constraints_error =
|
|||
borrowck_limitations_implies_static =
|
||||
due to current limitations in the borrow checker, this implies a `'static` lifetime
|
||||
|
||||
borrowck_long_type_consider_verbose = consider using `--verbose` to print the full type name to the console
|
||||
borrowck_long_type_full_path = the full type name has been written to '{$path}'
|
||||
|
||||
borrowck_move_closure_suggestion =
|
||||
consider adding 'move' keyword before the nested closure
|
||||
|
||||
|
|
|
|||
|
|
@ -289,8 +289,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
None => "value".to_owned(),
|
||||
};
|
||||
if needs_note {
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(ty, &mut path);
|
||||
let ty = self.infcx.tcx.short_string(ty, err.long_ty_path());
|
||||
if let Some(local) = place.as_local() {
|
||||
let span = self.body.local_decls[local].source_info.span;
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
|
|
@ -306,11 +305,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
place: ¬e_msg,
|
||||
});
|
||||
};
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if let UseSpans::FnSelfUse {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::collections::BTreeMap;
|
|||
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan};
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify};
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::{self as hir, CoroutineKind, LangItem};
|
||||
use rustc_index::IndexSlice;
|
||||
|
|
@ -29,7 +29,7 @@ use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
|||
use rustc_trait_selection::error_reporting::traits::call_kind::{CallDesugaringKind, call_kind};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
FulfillmentErrorCode, type_known_to_meet_bound_modulo_regions,
|
||||
FulfillmentError, FulfillmentErrorCode, type_known_to_meet_bound_modulo_regions,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -1434,17 +1434,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
error.obligation.predicate,
|
||||
)
|
||||
}
|
||||
[errors @ .., last] => {
|
||||
_ => {
|
||||
format!(
|
||||
"you could `clone` the value and consume it, if the \
|
||||
following trait bounds could be satisfied: \
|
||||
{} and `{}`",
|
||||
errors
|
||||
.iter()
|
||||
.map(|e| format!("`{}`", e.obligation.predicate))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
last.obligation.predicate,
|
||||
following trait bounds could be satisfied: {}",
|
||||
listify(&errors, |e: &FulfillmentError<'tcx>| format!(
|
||||
"`{}`",
|
||||
e.obligation.predicate
|
||||
))
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -596,19 +596,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, place_ty, expr, None);
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path);
|
||||
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
binds_to.sort();
|
||||
binds_to.dedup();
|
||||
|
|
@ -635,19 +629,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, place_ty, expr, Some(use_spans));
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path);
|
||||
let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty,
|
||||
place: &place_desc,
|
||||
span: use_span,
|
||||
});
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
use_spans.args_subdiag(err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
|
||||
|
|
@ -845,19 +833,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, bind_to.ty, expr, None);
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(bind_to.ty, &mut path);
|
||||
let ty = self.infcx.tcx.short_string(bind_to.ty, err.long_ty_path());
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty,
|
||||
place: place_desc,
|
||||
span: binding_span,
|
||||
});
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -458,13 +458,6 @@ pub(crate) enum OnClosureNote<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(borrowck_long_type_full_path)]
|
||||
#[note(borrowck_long_type_consider_verbose)]
|
||||
pub(crate) struct LongTypePath {
|
||||
pub(crate) path: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum TypeNoCopy<'a> {
|
||||
#[label(borrowck_ty_no_impl_copy)]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ use rustc_ast::{
|
|||
token,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans};
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans, listify, pluralize,
|
||||
};
|
||||
use rustc_expand::base::*;
|
||||
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
|
||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId};
|
||||
|
|
@ -975,15 +977,11 @@ fn report_invalid_references(
|
|||
} else {
|
||||
MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect())
|
||||
};
|
||||
let arg_list = if let &[index] = &indexes[..] {
|
||||
format!("argument {index}")
|
||||
} else {
|
||||
let tail = indexes.pop().unwrap();
|
||||
format!(
|
||||
"arguments {head} and {tail}",
|
||||
head = indexes.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(", ")
|
||||
)
|
||||
};
|
||||
let arg_list = format!(
|
||||
"argument{} {}",
|
||||
pluralize!(indexes.len()),
|
||||
listify(&indexes, |i: &usize| i.to_string()).unwrap_or_default()
|
||||
);
|
||||
e = ecx.dcx().struct_span_err(
|
||||
span,
|
||||
format!("invalid reference to positional {arg_list} ({num_args_desc})"),
|
||||
|
|
|
|||
|
|
@ -692,7 +692,7 @@ pub(crate) fn run_aot(
|
|||
|
||||
if tcx.dep_graph.is_fully_enabled() {
|
||||
for cgu in cgus {
|
||||
tcx.ensure().codegen_unit(cgu.name());
|
||||
tcx.ensure_ok().codegen_unit(cgu.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
// unnecessarily.
|
||||
if tcx.dep_graph.is_fully_enabled() {
|
||||
for cgu in codegen_units {
|
||||
tcx.ensure().codegen_unit(cgu.name());
|
||||
tcx.ensure_ok().codegen_unit(cgu.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
|
|||
if let Some(pp_mode) = sess.opts.pretty {
|
||||
if pp_mode.needs_ast_map() {
|
||||
create_and_enter_global_ctxt(compiler, krate, |tcx| {
|
||||
tcx.ensure().early_lint_checks(());
|
||||
tcx.ensure_ok().early_lint_checks(());
|
||||
pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx });
|
||||
passes::write_dep_info(tcx);
|
||||
});
|
||||
|
|
@ -365,7 +365,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
|
|||
return early_exit();
|
||||
}
|
||||
|
||||
tcx.ensure().analysis(());
|
||||
tcx.ensure_ok().analysis(());
|
||||
|
||||
if callbacks.after_analysis(compiler, tcx) == Compilation::Stop {
|
||||
return early_exit();
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ impl<'tcx> PrintExtra<'tcx> {
|
|||
|
||||
pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
|
||||
if ppm.needs_analysis() {
|
||||
ex.tcx().ensure().analysis(());
|
||||
ex.tcx().ensure_ok().analysis(());
|
||||
}
|
||||
|
||||
let (src, src_name) = get_source(sess);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::hash::{Hash, Hasher};
|
|||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::panic;
|
||||
use std::path::PathBuf;
|
||||
use std::thread::panicking;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
|
|
@ -301,6 +302,7 @@ pub struct DiagInner {
|
|||
|
||||
pub is_lint: Option<IsLint>,
|
||||
|
||||
pub long_ty_path: Option<PathBuf>,
|
||||
/// With `-Ztrack_diagnostics` enabled,
|
||||
/// we print where in rustc this error was emitted.
|
||||
pub(crate) emitted_at: DiagLocation,
|
||||
|
|
@ -324,6 +326,7 @@ impl DiagInner {
|
|||
args: Default::default(),
|
||||
sort_span: DUMMY_SP,
|
||||
is_lint: None,
|
||||
long_ty_path: None,
|
||||
emitted_at: DiagLocation::caller(),
|
||||
}
|
||||
}
|
||||
|
|
@ -1293,9 +1296,37 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// `cancel`, etc. Afterwards, `drop` is the only code that will be run on
|
||||
/// `self`.
|
||||
fn take_diag(&mut self) -> DiagInner {
|
||||
if let Some(path) = &self.long_ty_path {
|
||||
self.note(format!(
|
||||
"the full name for the type has been written to '{}'",
|
||||
path.display()
|
||||
));
|
||||
self.note("consider using `--verbose` to print the full type name to the console");
|
||||
}
|
||||
Box::into_inner(self.diag.take().unwrap())
|
||||
}
|
||||
|
||||
/// This method allows us to access the path of the file where "long types" are written to.
|
||||
///
|
||||
/// When calling `Diag::emit`, as part of that we will check if a `long_ty_path` has been set,
|
||||
/// and if it has been then we add a note mentioning the file where the "long types" were
|
||||
/// written to.
|
||||
///
|
||||
/// When calling `tcx.short_string()` after a `Diag` is constructed, the preferred way of doing
|
||||
/// so is `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that
|
||||
/// keeps the existence of a "long type" anywhere in the diagnostic, so the note telling the
|
||||
/// user where we wrote the file to is only printed once at most, *and* it makes it much harder
|
||||
/// to forget to set it.
|
||||
///
|
||||
/// If the diagnostic hasn't been created before a "short ty string" is created, then you should
|
||||
/// ensure that this method is called to set it `*diag.long_ty_path() = path`.
|
||||
///
|
||||
/// As a rule of thumb, if you see or add at least one `tcx.short_string()` call anywhere, in a
|
||||
/// scope, `diag.long_ty_path()` should be called once somewhere close by.
|
||||
pub fn long_ty_path(&mut self) -> &mut Option<PathBuf> {
|
||||
&mut self.long_ty_path
|
||||
}
|
||||
|
||||
/// Most `emit_producing_guarantee` functions use this as a starting point.
|
||||
fn emit_producing_nothing(mut self) {
|
||||
let diag = self.take_diag();
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ pub use rustc_error_messages::{
|
|||
SubdiagMessage, fallback_fluent_bundle, fluent_bundle,
|
||||
};
|
||||
use rustc_lint_defs::LintExpectationId;
|
||||
pub use rustc_lint_defs::{Applicability, pluralize};
|
||||
pub use rustc_lint_defs::{Applicability, listify, pluralize};
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
pub use rustc_span::ErrorGuaranteed;
|
||||
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
|
||||
|
|
@ -1999,18 +1999,6 @@ pub fn a_or_an(s: &str) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
/// Grammatical tool for displaying messages to end users in a nice form.
|
||||
///
|
||||
/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c"
|
||||
pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
|
||||
match v {
|
||||
[] => "".to_string(),
|
||||
[a] => a.to_string(),
|
||||
[a, b] => format!("{a} and {b}"),
|
||||
[a, v @ ..] => format!("{a}, {}", display_list_with_comma_and(v)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
||||
pub enum TerminalUrl {
|
||||
No,
|
||||
|
|
|
|||
|
|
@ -778,13 +778,13 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Static { .. } => {
|
||||
tcx.ensure().typeck(def_id);
|
||||
tcx.ensure_ok().typeck(def_id);
|
||||
maybe_check_static_with_link_section(tcx, def_id);
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
}
|
||||
DefKind::Const => {
|
||||
tcx.ensure().typeck(def_id);
|
||||
tcx.ensure_ok().typeck(def_id);
|
||||
}
|
||||
DefKind::Enum => {
|
||||
check_enum(tcx, def_id);
|
||||
|
|
@ -804,7 +804,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
DefKind::Impl { of_trait } => {
|
||||
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
|
||||
if tcx
|
||||
.ensure()
|
||||
.ensure_ok()
|
||||
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
|
||||
.is_ok()
|
||||
{
|
||||
|
|
@ -1042,7 +1042,7 @@ fn check_impl_items_against_trait<'tcx>(
|
|||
continue;
|
||||
};
|
||||
|
||||
let res = tcx.ensure().compare_impl_item(impl_item.expect_local());
|
||||
let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local());
|
||||
|
||||
if res.is_ok() {
|
||||
match ty_impl_item.kind {
|
||||
|
|
@ -1488,7 +1488,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
|
||||
for v in def.variants() {
|
||||
if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
|
||||
tcx.ensure().typeck(discr_def_id.expect_local());
|
||||
tcx.ensure_ok().typeck(discr_def_id.expect_local());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2034,7 +2034,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
tcx.ensure().coherent_trait(impl_trait_ref.def_id)?;
|
||||
tcx.ensure_ok().coherent_trait(impl_trait_ref.def_id)?;
|
||||
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
debug!(?param_env);
|
||||
|
|
|
|||
|
|
@ -1046,7 +1046,7 @@ fn check_associated_item(
|
|||
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
tcx.ensure()
|
||||
tcx.ensure_ok()
|
||||
.coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;
|
||||
|
||||
let self_ty = match item.container {
|
||||
|
|
@ -1354,7 +1354,7 @@ fn check_impl<'tcx>(
|
|||
let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
tcx.ensure().coherent_trait(trait_ref.def_id)?;
|
||||
tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;
|
||||
let trait_span = hir_trait_ref.path.span;
|
||||
let trait_ref = wfcx.normalize(
|
||||
trait_span,
|
||||
|
|
@ -2268,11 +2268,13 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
|||
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
|
||||
let items = tcx.hir_module_items(module);
|
||||
let res = items
|
||||
.par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id))
|
||||
.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
|
||||
.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
|
||||
.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
|
||||
.and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
|
||||
.par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))
|
||||
.and(items.par_impl_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)))
|
||||
.and(items.par_trait_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)))
|
||||
.and(
|
||||
items.par_foreign_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)),
|
||||
)
|
||||
.and(items.par_opaques(|item| tcx.ensure_ok().check_well_formed(item)));
|
||||
if module == LocalModDefId::CRATE_DEF_ID {
|
||||
super::entry::check_for_entry_fn(tcx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E
|
|||
// errors; other parts of the code may demand it for the info of
|
||||
// course.
|
||||
let span = tcx.def_span(impl_did);
|
||||
tcx.at(span).ensure().coerce_unsized_info(impl_did)
|
||||
tcx.at(span).ensure_ok().coerce_unsized_info(impl_did)
|
||||
}
|
||||
|
||||
fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
|
|||
let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) };
|
||||
// Trigger building the specialization graph for the trait. This will detect and report any
|
||||
// overlap errors.
|
||||
let mut res = tcx.ensure().specialization_graph_of(def_id);
|
||||
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
|
||||
|
||||
for &impl_def_id in impls {
|
||||
let trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
|
||||
|
|
@ -162,7 +162,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
|
|||
.and(check_impl(tcx, impl_def_id, trait_ref, trait_def))
|
||||
.and(check_object_overlap(tcx, impl_def_id, trait_ref))
|
||||
.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def))
|
||||
.and(tcx.ensure().orphan_check_impl(impl_def_id))
|
||||
.and(tcx.ensure_ok().orphan_check_impl(impl_def_id))
|
||||
.and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -292,16 +292,16 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {}
|
||||
hir::GenericParamKind::Type { default: Some(_), .. } => {
|
||||
self.tcx.ensure().type_of(param.def_id);
|
||||
self.tcx.ensure_ok().type_of(param.def_id);
|
||||
}
|
||||
hir::GenericParamKind::Type { .. } => {}
|
||||
hir::GenericParamKind::Const { default, .. } => {
|
||||
self.tcx.ensure().type_of(param.def_id);
|
||||
self.tcx.ensure_ok().type_of(param.def_id);
|
||||
if let Some(default) = default {
|
||||
// need to store default and type of default
|
||||
self.tcx.ensure().const_param_default(param.def_id);
|
||||
self.tcx.ensure_ok().const_param_default(param.def_id);
|
||||
if let hir::ConstArgKind::Anon(ac) = default.kind {
|
||||
self.tcx.ensure().type_of(ac.def_id);
|
||||
self.tcx.ensure_ok().type_of(ac.def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -312,8 +312,8 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||
|
||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Closure(closure) = expr.kind {
|
||||
self.tcx.ensure().generics_of(closure.def_id);
|
||||
self.tcx.ensure().codegen_fn_attrs(closure.def_id);
|
||||
self.tcx.ensure_ok().generics_of(closure.def_id);
|
||||
self.tcx.ensure_ok().codegen_fn_attrs(closure.def_id);
|
||||
// We do not call `type_of` for closures here as that
|
||||
// depends on typecheck and would therefore hide
|
||||
// any further errors in case one typeck fails.
|
||||
|
|
@ -325,15 +325,15 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||
/// `check_item_type` ensures that it's called instead.
|
||||
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
|
||||
let def_id = opaque.def_id;
|
||||
self.tcx.ensure().generics_of(def_id);
|
||||
self.tcx.ensure().predicates_of(def_id);
|
||||
self.tcx.ensure().explicit_item_bounds(def_id);
|
||||
self.tcx.ensure().explicit_item_self_bounds(def_id);
|
||||
self.tcx.ensure().item_bounds(def_id);
|
||||
self.tcx.ensure().item_self_bounds(def_id);
|
||||
self.tcx.ensure_ok().generics_of(def_id);
|
||||
self.tcx.ensure_ok().predicates_of(def_id);
|
||||
self.tcx.ensure_ok().explicit_item_bounds(def_id);
|
||||
self.tcx.ensure_ok().explicit_item_self_bounds(def_id);
|
||||
self.tcx.ensure_ok().item_bounds(def_id);
|
||||
self.tcx.ensure_ok().item_self_bounds(def_id);
|
||||
if self.tcx.is_conditionally_const(def_id) {
|
||||
self.tcx.ensure().explicit_implied_const_bounds(def_id);
|
||||
self.tcx.ensure().const_conditions(def_id);
|
||||
self.tcx.ensure_ok().explicit_implied_const_bounds(def_id);
|
||||
self.tcx.ensure_ok().const_conditions(def_id);
|
||||
}
|
||||
intravisit::walk_opaque_ty(self, opaque);
|
||||
}
|
||||
|
|
@ -683,20 +683,20 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
hir::ItemKind::ForeignMod { items, .. } => {
|
||||
for item in *items {
|
||||
let item = tcx.hir().foreign_item(item.id);
|
||||
tcx.ensure().generics_of(item.owner_id);
|
||||
tcx.ensure().type_of(item.owner_id);
|
||||
tcx.ensure().predicates_of(item.owner_id);
|
||||
tcx.ensure_ok().generics_of(item.owner_id);
|
||||
tcx.ensure_ok().type_of(item.owner_id);
|
||||
tcx.ensure_ok().predicates_of(item.owner_id);
|
||||
if tcx.is_conditionally_const(def_id) {
|
||||
tcx.ensure().explicit_implied_const_bounds(def_id);
|
||||
tcx.ensure().const_conditions(def_id);
|
||||
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
|
||||
tcx.ensure_ok().const_conditions(def_id);
|
||||
}
|
||||
match item.kind {
|
||||
hir::ForeignItemKind::Fn(..) => {
|
||||
tcx.ensure().codegen_fn_attrs(item.owner_id);
|
||||
tcx.ensure().fn_sig(item.owner_id)
|
||||
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
||||
tcx.ensure_ok().fn_sig(item.owner_id)
|
||||
}
|
||||
hir::ForeignItemKind::Static(..) => {
|
||||
tcx.ensure().codegen_fn_attrs(item.owner_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_foreign_item(item);
|
||||
placeholder_type_error(
|
||||
|
|
@ -713,40 +713,40 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
}
|
||||
}
|
||||
hir::ItemKind::Enum(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
lower_enum_variant_types(tcx, def_id.to_def_id());
|
||||
}
|
||||
hir::ItemKind::Impl { .. } => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().impl_trait_header(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().associated_items(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().impl_trait_header(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
}
|
||||
hir::ItemKind::Trait(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().trait_def(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().trait_def(def_id);
|
||||
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().associated_items(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
}
|
||||
hir::ItemKind::TraitAlias(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.at(it.span).explicit_implied_predicates_of(def_id);
|
||||
tcx.at(it.span).explicit_super_predicates_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
|
||||
for f in struct_def.fields() {
|
||||
tcx.ensure().generics_of(f.def_id);
|
||||
tcx.ensure().type_of(f.def_id);
|
||||
tcx.ensure().predicates_of(f.def_id);
|
||||
tcx.ensure_ok().generics_of(f.def_id);
|
||||
tcx.ensure_ok().type_of(f.def_id);
|
||||
tcx.ensure_ok().predicates_of(f.def_id);
|
||||
}
|
||||
|
||||
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
|
||||
|
|
@ -755,15 +755,15 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
}
|
||||
|
||||
hir::ItemKind::TyAlias(..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
if !ty.is_suggestable_infer_ty() {
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_item(it);
|
||||
|
|
@ -779,11 +779,11 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
}
|
||||
|
||||
hir::ItemKind::Fn { .. } => {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure().fn_sig(def_id);
|
||||
tcx.ensure().codegen_fn_attrs(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -791,18 +791,18 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
||||
let trait_item = tcx.hir().trait_item(trait_item_id);
|
||||
let def_id = trait_item_id.owner_id;
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
let icx = ItemCtxt::new(tcx, def_id.def_id);
|
||||
|
||||
match trait_item.kind {
|
||||
hir::TraitItemKind::Fn(..) => {
|
||||
tcx.ensure().codegen_fn_attrs(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().fn_sig(def_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
}
|
||||
|
||||
hir::TraitItemKind::Const(ty, body_id) => {
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
|
||||
&& !(ty.is_suggestable_infer_ty() && body_id.is_some())
|
||||
{
|
||||
|
|
@ -821,9 +821,9 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|||
}
|
||||
|
||||
hir::TraitItemKind::Type(_, Some(_)) => {
|
||||
tcx.ensure().item_bounds(def_id);
|
||||
tcx.ensure().item_self_bounds(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure_ok().item_bounds(def_id);
|
||||
tcx.ensure_ok().item_self_bounds(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
// Account for `type T = _;`.
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
visitor.visit_trait_item(trait_item);
|
||||
|
|
@ -838,8 +838,8 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|||
}
|
||||
|
||||
hir::TraitItemKind::Type(_, None) => {
|
||||
tcx.ensure().item_bounds(def_id);
|
||||
tcx.ensure().item_self_bounds(def_id);
|
||||
tcx.ensure_ok().item_bounds(def_id);
|
||||
tcx.ensure_ok().item_self_bounds(def_id);
|
||||
// #74612: Visit and try to find bad placeholders
|
||||
// even if there is no concrete type.
|
||||
let mut visitor = HirPlaceholderCollector::default();
|
||||
|
|
@ -856,20 +856,20 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
|
|||
}
|
||||
};
|
||||
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
||||
let def_id = impl_item_id.owner_id;
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
let impl_item = tcx.hir().impl_item(impl_item_id);
|
||||
let icx = ItemCtxt::new(tcx, def_id.def_id);
|
||||
match impl_item.kind {
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
tcx.ensure().codegen_fn_attrs(def_id);
|
||||
tcx.ensure().fn_sig(def_id);
|
||||
tcx.ensure_ok().codegen_fn_attrs(def_id);
|
||||
tcx.ensure_ok().fn_sig(def_id);
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {
|
||||
// Account for `type T = _;`
|
||||
|
|
@ -904,9 +904,9 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
|
|||
}
|
||||
|
||||
fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
tcx.ensure().generics_of(def_id);
|
||||
tcx.ensure().type_of(def_id);
|
||||
tcx.ensure().predicates_of(def_id);
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
}
|
||||
|
||||
fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
||||
|
|
@ -937,9 +937,9 @@ fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
|||
);
|
||||
|
||||
for f in &variant.fields {
|
||||
tcx.ensure().generics_of(f.did);
|
||||
tcx.ensure().type_of(f.did);
|
||||
tcx.ensure().predicates_of(f.did);
|
||||
tcx.ensure_ok().generics_of(f.did);
|
||||
tcx.ensure_ok().type_of(f.did);
|
||||
tcx.ensure_ok().predicates_of(f.did);
|
||||
}
|
||||
|
||||
// Lower the ctor, if any. This also registers the variant as an item.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use rustc_data_structures::sorted_map::SortedMap;
|
|||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err,
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -808,14 +808,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.map(|(trait_, mut assocs)| {
|
||||
assocs.sort();
|
||||
let trait_ = trait_.print_trait_sugared();
|
||||
format!("{} in `{trait_}`", match &assocs[..] {
|
||||
[] => String::new(),
|
||||
[only] => format!("`{only}`"),
|
||||
[assocs @ .., last] => format!(
|
||||
"{} and `{last}`",
|
||||
assocs.iter().map(|a| format!("`{a}`")).collect::<Vec<_>>().join(", ")
|
||||
),
|
||||
})
|
||||
format!(
|
||||
"{} in `{trait_}`",
|
||||
listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
names.sort();
|
||||
|
|
@ -1075,18 +1071,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
})
|
||||
.collect();
|
||||
let this_type = match &types_and_spans[..] {
|
||||
[.., _, (last, _)] => format!(
|
||||
"{} and {last}",
|
||||
types_and_spans[..types_and_spans.len() - 1]
|
||||
.iter()
|
||||
.map(|(x, _)| x.as_str())
|
||||
.intersperse(", ")
|
||||
.collect::<String>()
|
||||
),
|
||||
[(only, _)] => only.to_string(),
|
||||
[] => bug!("expected one segment to deny"),
|
||||
};
|
||||
let this_type = listify(&types_and_spans, |(t, _)| t.to_string())
|
||||
.expect("expected one segment to deny");
|
||||
|
||||
let arg_spans: Vec<Span> = segments
|
||||
.clone()
|
||||
|
|
@ -1102,21 +1088,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
ProhibitGenericsArg::Infer => kinds.push("generic"),
|
||||
});
|
||||
|
||||
let (kind, s) = match kinds[..] {
|
||||
[.., _, last] => (
|
||||
format!(
|
||||
"{} and {last}",
|
||||
kinds[..kinds.len() - 1]
|
||||
.iter()
|
||||
.map(|&x| x)
|
||||
.intersperse(", ")
|
||||
.collect::<String>()
|
||||
),
|
||||
"s",
|
||||
),
|
||||
[only] => (only.to_string(), ""),
|
||||
[] => bug!("expected at least one generic to prohibit"),
|
||||
};
|
||||
let s = pluralize!(kinds.len());
|
||||
let kind =
|
||||
listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit");
|
||||
let last_span = *arg_spans.last().unwrap();
|
||||
let span: MultiSpan = arg_spans.into();
|
||||
let mut err = struct_span_code_err!(
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ pub(crate) fn check_impl_wf(
|
|||
// Check that the args are constrained. We queryfied the check for ty/const params
|
||||
// since unconstrained type/const params cause ICEs in projection, so we want to
|
||||
// detect those specifically and project those to `TyKind::Error`.
|
||||
let mut res = tcx.ensure().enforce_impl_non_lifetime_params_are_constrained(impl_def_id);
|
||||
let mut res = tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id);
|
||||
res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id));
|
||||
|
||||
if tcx.features().min_specialization() {
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ use rustc_middle::middle;
|
|||
use rustc_middle::mir::interpret::GlobalId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
pub use crate::collect::suggest_impl_trait;
|
||||
|
|
@ -139,16 +139,20 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
let _prof_timer = tcx.sess.timer("type_check_crate");
|
||||
|
||||
tcx.sess.time("coherence_checking", || {
|
||||
// When discarding query call results, use an explicit type to indicate
|
||||
// what we are intending to discard, to help future type-based refactoring.
|
||||
type R = Result<(), ErrorGuaranteed>;
|
||||
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
let _ = tcx.ensure().check_mod_type_wf(module);
|
||||
let _: R = tcx.ensure_ok().check_mod_type_wf(module);
|
||||
});
|
||||
|
||||
for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
|
||||
let _ = tcx.ensure().coherent_trait(trait_def_id);
|
||||
let _: R = tcx.ensure_ok().coherent_trait(trait_def_id);
|
||||
}
|
||||
// these queries are executed for side-effects (error reporting):
|
||||
let _ = tcx.ensure().crate_inherent_impls_validity_check(());
|
||||
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
|
||||
let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(());
|
||||
let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(());
|
||||
});
|
||||
|
||||
if tcx.features().rustc_attrs() {
|
||||
|
|
@ -167,12 +171,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
tcx.hir().par_body_owners(|item_def_id| {
|
||||
let def_kind = tcx.def_kind(item_def_id);
|
||||
match def_kind {
|
||||
DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id),
|
||||
DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id),
|
||||
DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
|
||||
let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
let typing_env = ty::TypingEnv::fully_monomorphized();
|
||||
tcx.ensure().eval_to_const_value_raw(typing_env.as_query_input(cid));
|
||||
tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
|
@ -185,11 +189,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
tcx.hir().par_body_owners(|item_def_id| {
|
||||
let def_kind = tcx.def_kind(item_def_id);
|
||||
if !matches!(def_kind, DefKind::AnonConst) {
|
||||
tcx.ensure().typeck(item_def_id);
|
||||
tcx.ensure_ok().typeck(item_def_id);
|
||||
}
|
||||
});
|
||||
|
||||
tcx.ensure().check_unused_traits(());
|
||||
tcx.ensure_ok().check_unused_traits(());
|
||||
}
|
||||
|
||||
/// Lower a [`hir::Ty`] to a [`Ty`].
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub(crate) fn check_legal_trait_for_method_call(
|
|||
};
|
||||
return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }));
|
||||
}
|
||||
tcx.ensure().coherent_trait(trait_id)
|
||||
tcx.ensure_ok().coherent_trait(trait_id)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_errors::{Applicability, Diag, MultiSpan};
|
||||
use rustc_errors::{Applicability, Diag, MultiSpan, listify};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
@ -1016,18 +1016,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
},
|
||||
self.tcx.def_path_str(candidate.item.container_id(self.tcx))
|
||||
),
|
||||
[.., last] if other_methods_in_scope.len() < 5 => {
|
||||
_ if other_methods_in_scope.len() < 5 => {
|
||||
format!(
|
||||
"the methods of the same name on {} and `{}`",
|
||||
other_methods_in_scope[..other_methods_in_scope.len() - 1]
|
||||
.iter()
|
||||
.map(|c| format!(
|
||||
"`{}`",
|
||||
self.tcx.def_path_str(c.item.container_id(self.tcx))
|
||||
))
|
||||
.collect::<Vec<String>>()
|
||||
.join(", "),
|
||||
self.tcx.def_path_str(last.item.container_id(self.tcx))
|
||||
"the methods of the same name on {}",
|
||||
listify(
|
||||
&other_methods_in_scope[..other_methods_in_scope.len() - 1],
|
||||
|c| format!("`{}`", self.tcx.def_path_str(c.item.container_id(self.tcx)))
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
_ => format!(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
|
|||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, pluralize,
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, listify, pluralize,
|
||||
struct_span_code_err,
|
||||
};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
|
|
@ -2188,13 +2188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
if !missing_mandatory_fields.is_empty() {
|
||||
let s = pluralize!(missing_mandatory_fields.len());
|
||||
let fields: Vec<_> =
|
||||
missing_mandatory_fields.iter().map(|f| format!("`{f}`")).collect();
|
||||
let fields = match &fields[..] {
|
||||
[] => unreachable!(),
|
||||
[only] => only.to_string(),
|
||||
[start @ .., last] => format!("{} and {last}", start.join(", ")),
|
||||
};
|
||||
let fields = listify(&missing_mandatory_fields, |f| format!("`{f}`")).unwrap();
|
||||
self.dcx()
|
||||
.struct_span_err(
|
||||
span.shrink_to_hi(),
|
||||
|
|
@ -2551,25 +2545,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.partition(|field| field.2);
|
||||
err.span_labels(used_private_fields.iter().map(|(_, span, _)| *span), "private field");
|
||||
if !remaining_private_fields.is_empty() {
|
||||
let remaining_private_fields_len = remaining_private_fields.len();
|
||||
let names = match &remaining_private_fields
|
||||
.iter()
|
||||
.map(|(name, _, _)| name)
|
||||
.collect::<Vec<_>>()[..]
|
||||
{
|
||||
_ if remaining_private_fields_len > 6 => String::new(),
|
||||
[name] => format!("`{name}` "),
|
||||
[names @ .., last] => {
|
||||
let names = names.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||
format!("{} and `{last}` ", names.join(", "))
|
||||
}
|
||||
[] => bug!("expected at least one private field to report"),
|
||||
let names = if remaining_private_fields.len() > 6 {
|
||||
String::new()
|
||||
} else {
|
||||
format!(
|
||||
"{} ",
|
||||
listify(&remaining_private_fields, |(name, _, _)| format!("`{name}`"))
|
||||
.expect("expected at least one private field to report")
|
||||
)
|
||||
};
|
||||
err.note(format!(
|
||||
"{}private field{s} {names}that {were} not provided",
|
||||
if used_fields.is_empty() { "" } else { "...and other " },
|
||||
s = pluralize!(remaining_private_fields_len),
|
||||
were = pluralize!("was", remaining_private_fields_len),
|
||||
s = pluralize!(remaining_private_fields.len()),
|
||||
were = pluralize!("was", remaining_private_fields.len()),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use itertools::Itertools;
|
|||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an,
|
||||
display_list_with_comma_and, pluralize,
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an, listify, pluralize,
|
||||
};
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -2462,7 +2461,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
param.span,
|
||||
format!(
|
||||
"{} need{} to match the {} type of this parameter",
|
||||
display_list_with_comma_and(&other_param_matched_names),
|
||||
listify(&other_param_matched_names, |n| n.to_string())
|
||||
.unwrap_or_default(),
|
||||
pluralize!(if other_param_matched_names.len() == 1 {
|
||||
0
|
||||
} else {
|
||||
|
|
@ -2477,7 +2477,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
format!(
|
||||
"this parameter needs to match the {} type of {}",
|
||||
matched_ty,
|
||||
display_list_with_comma_and(&other_param_matched_names),
|
||||
listify(&other_param_matched_names, |n| n.to_string())
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -2523,7 +2524,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
generic_param.span,
|
||||
format!(
|
||||
"{} {} reference this parameter `{}`",
|
||||
display_list_with_comma_and(¶m_idents_matching),
|
||||
listify(¶m_idents_matching, |n| n.to_string())
|
||||
.unwrap_or_default(),
|
||||
if param_idents_matching.len() == 2 { "both" } else { "all" },
|
||||
generic_param.name.ident().name,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use core::iter;
|
|||
use hir::def_id::LocalDefId;
|
||||
use rustc_ast::util::parser::ExprPrecedence;
|
||||
use rustc_data_structures::packed::Pu128;
|
||||
use rustc_errors::{Applicability, Diag, MultiSpan};
|
||||
use rustc_errors::{Applicability, Diag, MultiSpan, listify};
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
|
|
@ -1836,16 +1836,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
error.obligation.predicate,
|
||||
));
|
||||
}
|
||||
[errors @ .., last] => {
|
||||
_ => {
|
||||
diag.help(format!(
|
||||
"`Clone` is not implemented because the following trait bounds \
|
||||
could not be satisfied: {} and `{}`",
|
||||
errors
|
||||
.iter()
|
||||
.map(|e| format!("`{}`", e.obligation.predicate))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
last.obligation.predicate,
|
||||
could not be satisfied: {}",
|
||||
listify(&errors, |e| format!("`{}`", e.obligation.predicate))
|
||||
.unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
use core::ops::ControlFlow;
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use hir::Expr;
|
||||
use rustc_ast::ast::Mutability;
|
||||
|
|
@ -362,14 +363,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
|
||||
let mut file = None;
|
||||
let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file);
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
rcvr_expr.span,
|
||||
E0599,
|
||||
"cannot write into `{}`",
|
||||
ty_str
|
||||
self.tcx.short_string(rcvr_ty, &mut file),
|
||||
);
|
||||
*err.long_ty_path() = file;
|
||||
err.span_note(
|
||||
rcvr_expr.span,
|
||||
"must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
|
||||
|
|
@ -380,11 +381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
"a writer is needed before this format string",
|
||||
);
|
||||
};
|
||||
if let Some(file) = file {
|
||||
err.note(format!("the full type name has been written to '{}'", file.display()));
|
||||
err.note("consider using `--verbose` to print the full type name to the console");
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
|
|
@ -595,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
(predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
|
||||
} else {
|
||||
(
|
||||
tcx.short_ty_string(rcvr_ty, &mut ty_file),
|
||||
tcx.short_string(rcvr_ty, &mut ty_file),
|
||||
with_forced_trimmed_paths!(rcvr_ty.to_string()),
|
||||
)
|
||||
};
|
||||
|
|
@ -624,6 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span,
|
||||
item_name,
|
||||
&short_ty_str,
|
||||
&mut ty_file,
|
||||
) {
|
||||
return guar;
|
||||
}
|
||||
|
|
@ -635,6 +632,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
item_kind,
|
||||
item_name,
|
||||
&short_ty_str,
|
||||
&mut ty_file,
|
||||
) {
|
||||
return guar;
|
||||
}
|
||||
|
|
@ -728,10 +726,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty_str = short_ty_str;
|
||||
}
|
||||
|
||||
if let Some(file) = ty_file {
|
||||
err.note(format!("the full type name has been written to '{}'", file.display(),));
|
||||
err.note("consider using `--verbose` to print the full type name to the console");
|
||||
}
|
||||
if rcvr_ty.references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
|
@ -1314,7 +1308,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
|
||||
let actual_prefix = rcvr_ty.prefix_string(self.tcx);
|
||||
info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
|
||||
let mut long_ty_file = None;
|
||||
let (primary_message, label, notes) = if unimplemented_traits.len() == 1
|
||||
&& unimplemented_traits_only
|
||||
{
|
||||
|
|
@ -1329,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
let OnUnimplementedNote { message, label, notes, .. } = self
|
||||
.err_ctxt()
|
||||
.on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file);
|
||||
.on_unimplemented_note(trait_ref, &obligation, &mut ty_file);
|
||||
(message, label, notes)
|
||||
})
|
||||
.unwrap()
|
||||
|
|
@ -1343,15 +1336,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
)
|
||||
});
|
||||
err.primary_message(primary_message);
|
||||
if let Some(file) = long_ty_file {
|
||||
err.note(format!(
|
||||
"the full name for the type has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
err.note(
|
||||
"consider using `--verbose` to print the full type name to the console",
|
||||
);
|
||||
}
|
||||
if let Some(label) = label {
|
||||
custom_span_label = true;
|
||||
err.span_label(span, label);
|
||||
|
|
@ -2403,6 +2387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
span: Span,
|
||||
item_name: Ident,
|
||||
ty_str: &str,
|
||||
long_ty_path: &mut Option<PathBuf>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let SelfSource::MethodCall(expr) = source {
|
||||
for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
|
||||
|
|
@ -2460,7 +2445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
);
|
||||
if pick.is_ok() {
|
||||
let range_span = parent_expr.span.with_hi(expr.span.hi());
|
||||
return Err(self.dcx().emit_err(errors::MissingParenthesesInRange {
|
||||
let mut err = self.dcx().create_err(errors::MissingParenthesesInRange {
|
||||
span,
|
||||
ty_str: ty_str.to_string(),
|
||||
method_name: item_name.as_str().to_string(),
|
||||
|
|
@ -2469,7 +2454,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
left: range_span.shrink_to_lo(),
|
||||
right: range_span.shrink_to_hi(),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
*err.long_ty_path() = long_ty_path.take();
|
||||
return Err(err.emit());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2486,6 +2473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
item_kind: &str,
|
||||
item_name: Ident,
|
||||
ty_str: &str,
|
||||
long_ty_path: &mut Option<PathBuf>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let found_candidate = all_traits(self.tcx)
|
||||
.into_iter()
|
||||
|
|
@ -2526,6 +2514,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
item_name,
|
||||
ty_str
|
||||
);
|
||||
*err.long_ty_path() = long_ty_path.take();
|
||||
let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
|
||||
match expr.kind {
|
||||
ExprKind::Lit(lit) => {
|
||||
|
|
|
|||
|
|
@ -832,20 +832,20 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
sess.time("misc_checking_1", || {
|
||||
parallel!(
|
||||
{
|
||||
sess.time("looking_for_entry_point", || tcx.ensure().entry_fn(()));
|
||||
sess.time("looking_for_entry_point", || tcx.ensure_ok().entry_fn(()));
|
||||
|
||||
sess.time("looking_for_derive_registrar", || {
|
||||
tcx.ensure().proc_macro_decls_static(())
|
||||
tcx.ensure_ok().proc_macro_decls_static(())
|
||||
});
|
||||
|
||||
CStore::from_tcx(tcx).report_unused_deps(tcx);
|
||||
},
|
||||
{
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
tcx.ensure().check_mod_loops(module);
|
||||
tcx.ensure().check_mod_attrs(module);
|
||||
tcx.ensure().check_mod_naked_functions(module);
|
||||
tcx.ensure().check_mod_unstable_api_usage(module);
|
||||
tcx.ensure_ok().check_mod_loops(module);
|
||||
tcx.ensure_ok().check_mod_attrs(module);
|
||||
tcx.ensure_ok().check_mod_naked_functions(module);
|
||||
tcx.ensure_ok().check_mod_unstable_api_usage(module);
|
||||
});
|
||||
},
|
||||
{
|
||||
|
|
@ -858,8 +858,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
// since they might not otherwise get called.
|
||||
// This marks the corresponding crate-level attributes
|
||||
// as used, and ensures that their values are valid.
|
||||
tcx.ensure().limits(());
|
||||
tcx.ensure().stability_index(());
|
||||
tcx.ensure_ok().limits(());
|
||||
tcx.ensure_ok().stability_index(());
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
@ -868,7 +868,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
sess.time("MIR_coroutine_by_move_body", || {
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) {
|
||||
tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id);
|
||||
tcx.ensure_done().coroutine_by_move_body_def_id(def_id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -883,13 +883,13 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
tcx.hir().par_body_owners(|def_id| {
|
||||
// Run unsafety check because it's responsible for stealing and
|
||||
// deallocating THIR.
|
||||
tcx.ensure().check_unsafety(def_id);
|
||||
tcx.ensure().mir_borrowck(def_id)
|
||||
tcx.ensure_ok().check_unsafety(def_id);
|
||||
tcx.ensure_ok().mir_borrowck(def_id)
|
||||
});
|
||||
});
|
||||
sess.time("MIR_effect_checking", || {
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
tcx.ensure().has_ffi_unwind_calls(def_id);
|
||||
tcx.ensure_ok().has_ffi_unwind_calls(def_id);
|
||||
|
||||
// If we need to codegen, ensure that we emit all errors from
|
||||
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering
|
||||
|
|
@ -897,15 +897,15 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
if tcx.sess.opts.output_types.should_codegen()
|
||||
|| tcx.hir().body_const_context(def_id).is_some()
|
||||
{
|
||||
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
|
||||
tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
|
||||
}
|
||||
});
|
||||
});
|
||||
sess.time("coroutine_obligations", || {
|
||||
tcx.hir().par_body_owners(|def_id| {
|
||||
if tcx.is_coroutine(def_id.to_def_id()) {
|
||||
tcx.ensure().mir_coroutine_witnesses(def_id);
|
||||
tcx.ensure().check_coroutine_obligations(
|
||||
tcx.ensure_ok().mir_coroutine_witnesses(def_id);
|
||||
tcx.ensure_ok().check_coroutine_obligations(
|
||||
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
|
||||
);
|
||||
}
|
||||
|
|
@ -950,15 +950,16 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
|
|||
sess.time("misc_checking_3", || {
|
||||
parallel!(
|
||||
{
|
||||
tcx.ensure().effective_visibilities(());
|
||||
tcx.ensure_ok().effective_visibilities(());
|
||||
|
||||
parallel!(
|
||||
{
|
||||
tcx.ensure().check_private_in_public(());
|
||||
tcx.ensure_ok().check_private_in_public(());
|
||||
},
|
||||
{
|
||||
tcx.hir()
|
||||
.par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
tcx.ensure_ok().check_mod_deathness(module)
|
||||
});
|
||||
},
|
||||
{
|
||||
sess.time("lint_checking", || {
|
||||
|
|
@ -966,14 +967,14 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
|
|||
});
|
||||
},
|
||||
{
|
||||
tcx.ensure().clashing_extern_declarations(());
|
||||
tcx.ensure_ok().clashing_extern_declarations(());
|
||||
}
|
||||
);
|
||||
},
|
||||
{
|
||||
sess.time("privacy_checking_modules", || {
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
tcx.ensure().check_mod_privacy(module);
|
||||
tcx.ensure_ok().check_mod_privacy(module);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -981,7 +982,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
|
|||
|
||||
// This check has to be run after all lints are done processing. We don't
|
||||
// define a lint filter, as all lint checks should have finished at this point.
|
||||
sess.time("check_lint_expectations", || tcx.ensure().check_expectations(None));
|
||||
sess.time("check_lint_expectations", || tcx.ensure_ok().check_expectations(None));
|
||||
|
||||
// This query is only invoked normally if a diagnostic is emitted that needs any
|
||||
// diagnostic item. If the crate compiles without checking any diagnostic items,
|
||||
|
|
@ -1006,7 +1007,7 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
|
|||
)
|
||||
}) =>
|
||||
{
|
||||
tcx.ensure().trigger_delayed_bug(def_id);
|
||||
tcx.ensure_ok().trigger_delayed_bug(def_id);
|
||||
}
|
||||
|
||||
// Bare `#[rustc_error]`.
|
||||
|
|
|
|||
|
|
@ -458,7 +458,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
|
|||
|| {
|
||||
tcx.sess.time("module_lints", || {
|
||||
// Run per-module lints
|
||||
tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module));
|
||||
tcx.hir().par_for_each_module(|module| tcx.ensure_ok().lint_mod(module));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,23 @@ macro_rules! pluralize {
|
|||
};
|
||||
}
|
||||
|
||||
/// Grammatical tool for displaying messages to end users in a nice form.
|
||||
///
|
||||
/// Take a list of items and a function to turn those items into a `String`, and output a display
|
||||
/// friendly comma separated list of those items.
|
||||
// FIXME(estebank): this needs to be changed to go through the translation machinery.
|
||||
pub fn listify<T>(list: &[T], fmt: impl Fn(&T) -> String) -> Option<String> {
|
||||
Some(match list {
|
||||
[only] => fmt(&only),
|
||||
[others @ .., last] => format!(
|
||||
"{} and {}",
|
||||
others.iter().map(|i| fmt(i)).collect::<Vec<_>>().join(", "),
|
||||
fmt(&last),
|
||||
),
|
||||
[] => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Indicates the confidence in the correctness of a suggestion.
|
||||
///
|
||||
/// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion
|
||||
|
|
|
|||
|
|
@ -118,11 +118,17 @@ struct QueryModifiers {
|
|||
/// Generate a `feed` method to set the query's value from another query.
|
||||
feedable: Option<Ident>,
|
||||
|
||||
/// Forward the result on ensure if the query gets recomputed, and
|
||||
/// return `Ok(())` otherwise. Only applicable to queries returning
|
||||
/// `Result<T, ErrorGuaranteed>`. The `T` is not returned from `ensure`
|
||||
/// invocations.
|
||||
ensure_forwards_result_if_red: Option<Ident>,
|
||||
/// When this query is called via `tcx.ensure_ok()`, it returns
|
||||
/// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to
|
||||
/// be executed, and that execution returns an error, the error result is
|
||||
/// returned to the caller.
|
||||
///
|
||||
/// If execution is skipped, a synthetic `Ok(())` is returned, on the
|
||||
/// assumption that a query with all-green inputs must have succeeded.
|
||||
///
|
||||
/// Can only be applied to queries with a return value of
|
||||
/// `Result<_, ErrorGuaranteed>`.
|
||||
return_result_from_ensure_ok: Option<Ident>,
|
||||
}
|
||||
|
||||
fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
|
||||
|
|
@ -138,7 +144,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
|
|||
let mut depth_limit = None;
|
||||
let mut separate_provide_extern = None;
|
||||
let mut feedable = None;
|
||||
let mut ensure_forwards_result_if_red = None;
|
||||
let mut return_result_from_ensure_ok = None;
|
||||
|
||||
while !input.is_empty() {
|
||||
let modifier: Ident = input.parse()?;
|
||||
|
|
@ -200,8 +206,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
|
|||
try_insert!(separate_provide_extern = modifier);
|
||||
} else if modifier == "feedable" {
|
||||
try_insert!(feedable = modifier);
|
||||
} else if modifier == "ensure_forwards_result_if_red" {
|
||||
try_insert!(ensure_forwards_result_if_red = modifier);
|
||||
} else if modifier == "return_result_from_ensure_ok" {
|
||||
try_insert!(return_result_from_ensure_ok = modifier);
|
||||
} else {
|
||||
return Err(Error::new(modifier.span(), "unknown query modifier"));
|
||||
}
|
||||
|
|
@ -222,7 +228,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
|
|||
depth_limit,
|
||||
separate_provide_extern,
|
||||
feedable,
|
||||
ensure_forwards_result_if_red,
|
||||
return_result_from_ensure_ok,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -354,7 +360,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
|
|||
eval_always,
|
||||
depth_limit,
|
||||
separate_provide_extern,
|
||||
ensure_forwards_result_if_red,
|
||||
return_result_from_ensure_ok,
|
||||
);
|
||||
|
||||
if modifiers.cache.is_some() {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ macro_rules! provide_one {
|
|||
// doesn't need to do this (and can't, as it would cause a query cycle).
|
||||
use rustc_middle::dep_graph::dep_kinds;
|
||||
if dep_kinds::$name != dep_kinds::crate_hash && $tcx.dep_graph.is_fully_enabled() {
|
||||
$tcx.ensure().crate_hash($def_id.krate);
|
||||
$tcx.ensure_ok().crate_hash($def_id.krate);
|
||||
}
|
||||
|
||||
let cdata = rustc_data_structures::sync::FreezeReadGuard::map(CStore::from_tcx($tcx), |c| {
|
||||
|
|
|
|||
|
|
@ -2191,13 +2191,13 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
|
|||
let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id);
|
||||
|
||||
if encode_const {
|
||||
tcx.ensure_with_value().mir_for_ctfe(def_id);
|
||||
tcx.ensure_done().mir_for_ctfe(def_id);
|
||||
}
|
||||
if encode_opt {
|
||||
tcx.ensure_with_value().optimized_mir(def_id);
|
||||
tcx.ensure_done().optimized_mir(def_id);
|
||||
}
|
||||
if encode_opt || encode_const {
|
||||
tcx.ensure_with_value().promoted_mir(def_id);
|
||||
tcx.ensure_done().promoted_mir(def_id);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use super::{
|
|||
ReportedErrorInfo,
|
||||
};
|
||||
use crate::mir;
|
||||
use crate::query::TyCtxtEnsure;
|
||||
use crate::query::TyCtxtEnsureOk;
|
||||
use crate::ty::visit::TypeVisitableExt;
|
||||
use crate::ty::{self, GenericArgs, TyCtxt};
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxtEnsure<'tcx> {
|
||||
impl<'tcx> TyCtxtEnsureOk<'tcx> {
|
||||
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::TooGeneric` will be returned.
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ pub use keys::{AsLocalKey, Key, LocalCrate};
|
|||
pub mod on_disk_cache;
|
||||
#[macro_use]
|
||||
pub mod plumbing;
|
||||
pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue};
|
||||
pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk};
|
||||
|
||||
// Each of these queries corresponds to a function pointer field in the
|
||||
// `Providers` struct for requesting a value of that type, and a method
|
||||
|
|
@ -1087,7 +1087,7 @@ rustc_queries! {
|
|||
|
||||
query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
|
||||
desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
/// Caches `CoerceUnsized` kinds for impls on custom types.
|
||||
|
|
@ -1095,7 +1095,7 @@ rustc_queries! {
|
|||
desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
|
||||
|
|
@ -1110,7 +1110,7 @@ rustc_queries! {
|
|||
|
||||
query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> {
|
||||
desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
/// Borrow-checks the function body. If this is a closure, returns
|
||||
|
|
@ -1140,7 +1140,7 @@ rustc_queries! {
|
|||
/// </div>
|
||||
query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> {
|
||||
desc { "check for inherent impls that should not be defined in crate" }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
/// Checks all types in the crate for overlap in their inherent impls. Reports errors.
|
||||
|
|
@ -1152,7 +1152,7 @@ rustc_queries! {
|
|||
/// </div>
|
||||
query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> {
|
||||
desc { "check for overlap between inherent impls defined in this crate" }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
/// Checks whether all impls in the crate pass the overlap check, returning
|
||||
|
|
@ -1162,7 +1162,7 @@ rustc_queries! {
|
|||
"checking whether impl `{}` follows the orphan rules",
|
||||
tcx.def_path_str(key),
|
||||
}
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
/// Check whether the function has any recursion that could cause the inliner to trigger
|
||||
|
|
@ -1479,7 +1479,7 @@ rustc_queries! {
|
|||
query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> {
|
||||
desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
|
||||
cache_on_disk_if { true }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] {
|
||||
desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) }
|
||||
|
|
@ -1715,12 +1715,12 @@ rustc_queries! {
|
|||
|
||||
query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
// The `DefId`s of all non-generic functions and statics in the given crate
|
||||
|
|
@ -2442,7 +2442,7 @@ rustc_queries! {
|
|||
/// Any other def id will ICE.
|
||||
query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) }
|
||||
ensure_forwards_result_if_red
|
||||
return_result_from_ensure_ok
|
||||
}
|
||||
|
||||
query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] {
|
||||
|
|
|
|||
|
|
@ -88,30 +88,68 @@ impl<'tcx> Deref for TyCtxtAt<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TyCtxtEnsure<'tcx> {
|
||||
#[must_use]
|
||||
pub struct TyCtxtEnsureOk<'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TyCtxtEnsureWithValue<'tcx> {
|
||||
#[must_use]
|
||||
pub struct TyCtxtEnsureDone<'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Returns a transparent wrapper for `TyCtxt`, which ensures queries
|
||||
/// are executed instead of just returning their results.
|
||||
/// Wrapper that calls queries in a special "ensure OK" mode, for callers
|
||||
/// that don't need the return value and just want to invoke a query for
|
||||
/// its potential side-effect of emitting fatal errors.
|
||||
///
|
||||
/// This can be more efficient than a normal query call, because if the
|
||||
/// query's inputs are all green, the call can return immediately without
|
||||
/// needing to obtain a value (by decoding one from disk or by executing
|
||||
/// the query).
|
||||
///
|
||||
/// (As with all query calls, execution is also skipped if the query result
|
||||
/// is already cached in memory.)
|
||||
///
|
||||
/// ## WARNING
|
||||
/// A subsequent normal call to the same query might still cause it to be
|
||||
/// executed! This can occur when the inputs are all green, but the query's
|
||||
/// result is not cached on disk, so the query must be executed to obtain a
|
||||
/// return value.
|
||||
///
|
||||
/// Therefore, this call mode is not appropriate for callers that want to
|
||||
/// ensure that the query is _never_ executed in the future.
|
||||
///
|
||||
/// ## `return_result_from_ensure_ok`
|
||||
/// If a query has the `return_result_from_ensure_ok` modifier, calls via
|
||||
/// `ensure_ok` will instead return `Result<(), ErrorGuaranteed>`. If the
|
||||
/// query needs to be executed, and execution returns an error, that error
|
||||
/// is returned to the caller.
|
||||
#[inline(always)]
|
||||
pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
|
||||
TyCtxtEnsure { tcx: self }
|
||||
pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> {
|
||||
TyCtxtEnsureOk { tcx: self }
|
||||
}
|
||||
|
||||
/// Returns a transparent wrapper for `TyCtxt`, which ensures queries
|
||||
/// are executed instead of just returning their results.
|
||||
/// Wrapper that calls queries in a special "ensure done" mode, for callers
|
||||
/// that don't need the return value and just want to guarantee that the
|
||||
/// query won't be executed in the future, by executing it now if necessary.
|
||||
///
|
||||
/// This version verifies that the computed result exists in the cache before returning.
|
||||
/// This is useful for queries that read from a [`Steal`] value, to ensure
|
||||
/// that they are executed before the query that will steal the value.
|
||||
///
|
||||
/// Unlike [`Self::ensure_ok`], a query with all-green inputs will only be
|
||||
/// skipped if its return value is stored in the disk-cache. This is still
|
||||
/// more efficient than a regular query, because in that situation the
|
||||
/// return value doesn't necessarily need to be decoded.
|
||||
///
|
||||
/// (As with all query calls, execution is also skipped if the query result
|
||||
/// is already cached in memory.)
|
||||
///
|
||||
/// [`Steal`]: rustc_data_structures::steal::Steal
|
||||
#[inline(always)]
|
||||
pub fn ensure_with_value(self) -> TyCtxtEnsureWithValue<'tcx> {
|
||||
TyCtxtEnsureWithValue { tcx: self }
|
||||
pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> {
|
||||
TyCtxtEnsureDone { tcx: self }
|
||||
}
|
||||
|
||||
/// Returns a transparent wrapper for `TyCtxt` which uses
|
||||
|
|
@ -193,7 +231,7 @@ macro_rules! query_ensure {
|
|||
([]$($args:tt)*) => {
|
||||
query_ensure($($args)*)
|
||||
};
|
||||
([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => {
|
||||
([(return_result_from_ensure_ok) $($rest:tt)*]$($args:tt)*) => {
|
||||
query_ensure_error_guaranteed($($args)*).map(|_| ())
|
||||
};
|
||||
([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
|
||||
|
|
@ -248,15 +286,15 @@ macro_rules! separate_provide_extern_decl {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! ensure_result {
|
||||
([][$ty:ty]) => {
|
||||
macro_rules! ensure_ok_result {
|
||||
( [] ) => {
|
||||
()
|
||||
};
|
||||
([(ensure_forwards_result_if_red) $($rest:tt)*][$ty:ty]) => {
|
||||
( [(return_result_from_ensure_ok) $($rest:tt)*] ) => {
|
||||
Result<(), ErrorGuaranteed>
|
||||
};
|
||||
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
|
||||
ensure_result!([$($modifiers)*][$($args)*])
|
||||
( [$other:tt $($modifiers:tt)*] ) => {
|
||||
ensure_ok_result!( [$($modifiers)*] )
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -383,10 +421,13 @@ macro_rules! define_callbacks {
|
|||
$($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)*
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxtEnsure<'tcx> {
|
||||
impl<'tcx> TyCtxtEnsureOk<'tcx> {
|
||||
$($(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> ensure_result!([$($modifiers)*][$V]) {
|
||||
pub fn $name(
|
||||
self,
|
||||
key: query_helper_param_ty!($($K)*),
|
||||
) -> ensure_ok_result!([$($modifiers)*]) {
|
||||
query_ensure!(
|
||||
[$($modifiers)*]
|
||||
self.tcx,
|
||||
|
|
@ -398,7 +439,7 @@ macro_rules! define_callbacks {
|
|||
})*
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxtEnsureWithValue<'tcx> {
|
||||
impl<'tcx> TyCtxtEnsureDone<'tcx> {
|
||||
$($(#[$attr])*
|
||||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
|
||||
|
|
|
|||
|
|
@ -1957,7 +1957,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap {
|
||||
// Create a dependency to the crate to be sure we re-execute this when the amount of
|
||||
// definitions change.
|
||||
self.ensure().hir_crate(());
|
||||
self.ensure_ok().hir_crate(());
|
||||
// Freeze definitions once we start iterating on them, to prevent adding new ones
|
||||
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
|
||||
self.untracked.definitions.freeze().def_path_hash_to_def_index_map()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::ops::ControlFlow;
|
|||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, pluralize,
|
||||
Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, listify, pluralize,
|
||||
};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
@ -362,11 +362,8 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
let n = trait_names.len();
|
||||
let stable = if all_stable { "" } else { "unstable " };
|
||||
let trait_ = if all_known { format!("trait{}", pluralize!(n)) } else { String::new() };
|
||||
format!("{stable}{trait_}{}", match &trait_names[..] {
|
||||
[t] => format!(" {t}"),
|
||||
[ts @ .., last] => format!(" {} and {last}", ts.join(", ")),
|
||||
[] => return false,
|
||||
},)
|
||||
let Some(trait_names) = listify(&trait_names, |n| n.to_string()) else { return false };
|
||||
format!("{stable}{trait_} {trait_names}")
|
||||
} else {
|
||||
// We're more explicit when there's a mix of stable and unstable traits.
|
||||
let mut trait_names = constraints
|
||||
|
|
@ -378,10 +375,9 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
.collect::<Vec<_>>();
|
||||
trait_names.sort();
|
||||
trait_names.dedup();
|
||||
match &trait_names[..] {
|
||||
[t] => t.to_string(),
|
||||
[ts @ .., last] => format!("{} and {last}", ts.join(", ")),
|
||||
[] => return false,
|
||||
match listify(&trait_names, |t| t.to_string()) {
|
||||
Some(names) => names,
|
||||
None => return false,
|
||||
}
|
||||
};
|
||||
let constraint = constraint.join(" + ");
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_hir::def::{CtorOf, DefKind};
|
|||
use rustc_macros::extension;
|
||||
pub use rustc_type_ir::error::ExpectedFound;
|
||||
|
||||
use crate::ty::print::{FmtPrinter, PrettyPrinter, with_forced_trimmed_paths};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::print::{FmtPrinter, Print, with_forced_trimmed_paths};
|
||||
use crate::ty::{self, Lift, Ty, TyCtxt};
|
||||
|
||||
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
|
||||
|
||||
|
|
@ -159,8 +159,8 @@ impl<'tcx> Ty<'tcx> {
|
|||
ty::Error(_) => "type error".into(),
|
||||
_ => {
|
||||
let width = tcx.sess.diagnostic_width();
|
||||
let length_limit = std::cmp::max(width / 4, 15);
|
||||
format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into()
|
||||
let length_limit = std::cmp::max(width / 4, 40);
|
||||
format!("`{}`", tcx.string_with_limit(self, length_limit)).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -213,10 +213,14 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
|
||||
pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String
|
||||
where
|
||||
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy,
|
||||
<T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
|
||||
{
|
||||
let mut type_limit = 50;
|
||||
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
|
||||
cx.pretty_print_type(ty)
|
||||
self.lift(p).expect("could not lift for printing").print(cx)
|
||||
})
|
||||
.expect("could not write to `String`");
|
||||
if regular.len() <= length_limit {
|
||||
|
|
@ -231,7 +235,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
hir::def::Namespace::TypeNS,
|
||||
rustc_session::Limit(type_limit),
|
||||
);
|
||||
cx.pretty_print_type(ty).expect("could not write to `String`");
|
||||
self.lift(p)
|
||||
.expect("could not lift for printing")
|
||||
.print(&mut cx)
|
||||
.expect("could not print type");
|
||||
cx.into_buffer()
|
||||
});
|
||||
if short.len() <= length_limit || type_limit == 0 {
|
||||
|
|
@ -242,9 +249,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
short
|
||||
}
|
||||
|
||||
pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String {
|
||||
/// When calling this after a `Diag` is constructed, the preferred way of doing so is
|
||||
/// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps
|
||||
/// the existence of a "long type" anywhere in the diagnostic, so the note telling the user
|
||||
/// where we wrote the file to is only printed once.
|
||||
pub fn short_string<'a, T>(self, p: T, path: &mut Option<PathBuf>) -> String
|
||||
where
|
||||
T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift<TyCtxt<'tcx>> + Copy + Hash,
|
||||
<T as Lift<TyCtxt<'tcx>>>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>,
|
||||
{
|
||||
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
|
||||
cx.pretty_print_type(ty)
|
||||
self.lift(p).expect("could not lift for printing").print(cx)
|
||||
})
|
||||
.expect("could not write to `String`");
|
||||
|
||||
|
|
@ -257,13 +272,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
if regular.len() <= width * 2 / 3 {
|
||||
return regular;
|
||||
}
|
||||
let short = self.ty_string_with_limit(ty, length_limit);
|
||||
let short = self.string_with_limit(p, length_limit);
|
||||
if regular == short {
|
||||
return regular;
|
||||
}
|
||||
// Ensure we create an unique file for the type passed in when we create a file.
|
||||
let mut s = DefaultHasher::new();
|
||||
ty.hash(&mut s);
|
||||
p.hash(&mut s);
|
||||
let hash = s.finish();
|
||||
*path = Some(path.take().unwrap_or_else(|| {
|
||||
self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,10 @@ pub trait Printer<'tcx>: Sized {
|
|||
args: &[GenericArg<'tcx>],
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
fn should_truncate(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
// Defaults (should not be overridden):
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
|
|
|||
|
|
@ -865,7 +865,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
p!(write("{{"));
|
||||
if !self.tcx().sess.verbose_internals() {
|
||||
p!("coroutine witness");
|
||||
// FIXME(eddyb) should use `def_span`.
|
||||
if let Some(did) = did.as_local() {
|
||||
let span = self.tcx().def_span(did);
|
||||
p!(write(
|
||||
|
|
@ -887,26 +886,30 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
p!(write("{{"));
|
||||
if !self.should_print_verbose() {
|
||||
p!(write("closure"));
|
||||
// FIXME(eddyb) should use `def_span`.
|
||||
if let Some(did) = did.as_local() {
|
||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||
p!("@", print_def_path(did.to_def_id(), args));
|
||||
} else {
|
||||
let span = self.tcx().def_span(did);
|
||||
let preference = if with_forced_trimmed_paths() {
|
||||
FileNameDisplayPreference::Short
|
||||
} else {
|
||||
FileNameDisplayPreference::Remapped
|
||||
};
|
||||
p!(write(
|
||||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx().sess.source_map().span_to_string(span, preference)
|
||||
));
|
||||
}
|
||||
if self.should_truncate() {
|
||||
write!(self, "@...}}")?;
|
||||
return Ok(());
|
||||
} else {
|
||||
p!(write("@"), print_def_path(did, args));
|
||||
if let Some(did) = did.as_local() {
|
||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||
p!("@", print_def_path(did.to_def_id(), args));
|
||||
} else {
|
||||
let span = self.tcx().def_span(did);
|
||||
let preference = if with_forced_trimmed_paths() {
|
||||
FileNameDisplayPreference::Short
|
||||
} else {
|
||||
FileNameDisplayPreference::Remapped
|
||||
};
|
||||
p!(write(
|
||||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx().sess.source_map().span_to_string(span, preference)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
p!(write("@"), print_def_path(did, args));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p!(print_def_path(did, args));
|
||||
|
|
@ -942,7 +945,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
"coroutine from coroutine-closure should have CoroutineSource::Closure"
|
||||
),
|
||||
}
|
||||
// FIXME(eddyb) should use `def_span`.
|
||||
if let Some(did) = did.as_local() {
|
||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||
p!("@", print_def_path(did.to_def_id(), args));
|
||||
|
|
@ -1994,7 +1996,6 @@ pub struct FmtPrinterData<'a, 'tcx> {
|
|||
binder_depth: usize,
|
||||
printed_type_count: usize,
|
||||
type_length_limit: Limit,
|
||||
truncated: bool,
|
||||
|
||||
pub region_highlight_mode: RegionHighlightMode<'tcx>,
|
||||
|
||||
|
|
@ -2046,7 +2047,6 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
|||
binder_depth: 0,
|
||||
printed_type_count: 0,
|
||||
type_length_limit,
|
||||
truncated: false,
|
||||
region_highlight_mode: RegionHighlightMode::default(),
|
||||
ty_infer_name_resolver: None,
|
||||
const_infer_name_resolver: None,
|
||||
|
|
@ -2183,16 +2183,49 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
}
|
||||
|
||||
fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
|
||||
if self.type_length_limit.value_within_limit(self.printed_type_count) {
|
||||
self.printed_type_count += 1;
|
||||
self.pretty_print_type(ty)
|
||||
} else {
|
||||
self.truncated = true;
|
||||
write!(self, "...")?;
|
||||
Ok(())
|
||||
match ty.kind() {
|
||||
ty::Tuple(tys) if tys.len() == 0 && self.should_truncate() => {
|
||||
// Don't truncate `()`.
|
||||
self.printed_type_count += 1;
|
||||
self.pretty_print_type(ty)
|
||||
}
|
||||
ty::Adt(..)
|
||||
| ty::Foreign(_)
|
||||
| ty::Pat(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::UnsafeBinder(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Tuple(_)
|
||||
| ty::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(_)
|
||||
| ty::Error(_)
|
||||
if self.should_truncate() =>
|
||||
{
|
||||
// We only truncate types that we know are likely to be much longer than 3 chars.
|
||||
// There's no point in replacing `i32` or `!`.
|
||||
write!(self, "...")?;
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
self.printed_type_count += 1;
|
||||
self.pretty_print_type(ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn should_truncate(&mut self) -> bool {
|
||||
!self.type_length_limit.value_within_limit(self.printed_type_count)
|
||||
}
|
||||
|
||||
fn print_dyn_existential(
|
||||
&mut self,
|
||||
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
|
|
@ -2942,7 +2975,7 @@ impl<'tcx> ty::TraitPredicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
|
||||
pub struct TraitPredPrintWithBoundConstness<'tcx>(
|
||||
ty::TraitPredicate<'tcx>,
|
||||
Option<ty::BoundConstness>,
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
|
||||
) -> Option<ty::Destructor> {
|
||||
let drop_trait = self.lang_items().drop_trait()?;
|
||||
self.ensure().coherent_trait(drop_trait).ok()?;
|
||||
self.ensure_ok().coherent_trait(drop_trait).ok()?;
|
||||
|
||||
let ty = self.type_of(adt_did).instantiate_identity();
|
||||
let mut dtor_candidate = None;
|
||||
|
|
@ -404,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
|
||||
) -> Option<ty::AsyncDestructor> {
|
||||
let async_drop_trait = self.lang_items().async_drop_trait()?;
|
||||
self.ensure().coherent_trait(async_drop_trait).ok()?;
|
||||
self.ensure_ok().coherent_trait(async_drop_trait).ok()?;
|
||||
|
||||
let ty = self.type_of(adt_did).instantiate_identity();
|
||||
let mut dtor_candidate = None;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ mir_build_borrow_of_moved_value = borrow of moved value
|
|||
.occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait
|
||||
.value_borrowed_label = value borrowed here after move
|
||||
.suggestion = borrow this binding in the pattern to avoid moving the value
|
||||
.full_type_name = the full type name has been written to '{$path}'
|
||||
.consider_verbose = consider using `--verbose` to print the full type name to the console
|
||||
|
||||
mir_build_call_to_deprecated_safe_fn_requires_unsafe =
|
||||
call to deprecated safe function `{$function}` is unsafe and requires unsafe block
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
|
|||
/// Create the MIR for a given `DefId`, including unreachable code. Do not call
|
||||
/// this directly; instead use the cached version via `mir_built`.
|
||||
pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
|
||||
tcx.ensure_with_value().thir_abstract_const(def);
|
||||
tcx.ensure_done().thir_abstract_const(def);
|
||||
if let Err(e) = tcx.check_match(def) {
|
||||
return construct_error(tcx, def, e);
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
|
|||
// "not all control paths return a value" is reported here.
|
||||
//
|
||||
// maybe move the check to a MIR pass?
|
||||
tcx.ensure().check_liveness(def);
|
||||
tcx.ensure_ok().check_liveness(def);
|
||||
|
||||
// Don't steal here, instead steal in unsafeck. This is so that
|
||||
// pattern inline constants can be evaluated as part of building the
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
|||
fn visit_inner_body(&mut self, def: LocalDefId) {
|
||||
if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
|
||||
// Runs all other queries that depend on THIR.
|
||||
self.tcx.ensure_with_value().mir_built(def);
|
||||
self.tcx.ensure_done().mir_built(def);
|
||||
let inner_thir = &inner_thir.steal();
|
||||
let hir_context = self.tcx.local_def_id_to_hir_id(def);
|
||||
let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe);
|
||||
|
|
@ -1139,7 +1139,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
|
|||
|
||||
let Ok((thir, expr)) = tcx.thir_body(def) else { return };
|
||||
// Runs all other queries that depend on THIR.
|
||||
tcx.ensure_with_value().mir_built(def);
|
||||
tcx.ensure_done().mir_built(def);
|
||||
let thir = &thir.steal();
|
||||
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def);
|
||||
|
|
|
|||
|
|
@ -839,10 +839,6 @@ pub(crate) struct BorrowOfMovedValue {
|
|||
pub(crate) ty: String,
|
||||
#[suggestion(code = "ref ", applicability = "machine-applicable")]
|
||||
pub(crate) suggest_borrowing: Option<Span>,
|
||||
#[note(mir_build_full_type_name)]
|
||||
#[note(mir_build_consider_verbose)]
|
||||
pub(crate) has_path: bool,
|
||||
pub(crate) path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -797,16 +797,16 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
});
|
||||
if !conflicts_ref.is_empty() {
|
||||
let mut path = None;
|
||||
let ty = cx.tcx.short_ty_string(ty, &mut path);
|
||||
sess.dcx().emit_err(BorrowOfMovedValue {
|
||||
let ty = cx.tcx.short_string(ty, &mut path);
|
||||
let mut err = sess.dcx().create_err(BorrowOfMovedValue {
|
||||
binding_span: pat.span,
|
||||
conflicts_ref,
|
||||
name: Ident::new(name, pat.span),
|
||||
ty,
|
||||
suggest_borrowing: Some(pat.span.shrink_to_lo()),
|
||||
has_path: path.is_some(),
|
||||
path: path.map(|p| p.display().to_string()).unwrap_or_default(),
|
||||
});
|
||||
*err.long_ty_path() = path;
|
||||
err.emit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::iter;
|
|||
use std::ops::{Range, RangeFrom};
|
||||
|
||||
use rustc_abi::{ExternAbi, FieldIdx};
|
||||
use rustc_attr_parsing::InlineAttr;
|
||||
use rustc_attr_parsing::{InlineAttr, OptimizeAttr};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::Idx;
|
||||
|
|
@ -770,6 +770,10 @@ fn check_codegen_attributes<'tcx, I: Inliner<'tcx>>(
|
|||
return Err("never inline attribute");
|
||||
}
|
||||
|
||||
if let OptimizeAttr::DoNotOptimize = callee_attrs.optimize {
|
||||
return Err("has DoNotOptimize attribute");
|
||||
}
|
||||
|
||||
// Reachability pass defines which functions are eligible for inlining. Generally inlining
|
||||
// other functions is incorrect because they could reference symbols that aren't exported.
|
||||
let is_generic = callsite.callee.args.non_erasable_generics().next().is_some();
|
||||
|
|
|
|||
|
|
@ -421,11 +421,11 @@ fn mir_promoted(
|
|||
};
|
||||
|
||||
// the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run.
|
||||
tcx.ensure_with_value().has_ffi_unwind_calls(def);
|
||||
tcx.ensure_done().has_ffi_unwind_calls(def);
|
||||
|
||||
// the `by_move_body` query uses the raw mir, so make sure it is run.
|
||||
if tcx.needs_coroutine_by_move_body_def_id(def.to_def_id()) {
|
||||
tcx.ensure_with_value().coroutine_by_move_body_def_id(def);
|
||||
tcx.ensure_done().coroutine_by_move_body_def_id(def);
|
||||
}
|
||||
|
||||
let mut body = tcx.mir_built(def).steal();
|
||||
|
|
@ -488,7 +488,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
|
|||
/// end up missing the source MIR due to stealing happening.
|
||||
fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
|
||||
if tcx.is_coroutine(def.to_def_id()) {
|
||||
tcx.ensure_with_value().mir_coroutine_witnesses(def);
|
||||
tcx.ensure_done().mir_coroutine_witnesses(def);
|
||||
}
|
||||
|
||||
// We only need to borrowck non-synthetic MIR.
|
||||
|
|
@ -501,7 +501,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
|
|||
if pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed)
|
||||
|| inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id())
|
||||
{
|
||||
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id()));
|
||||
tcx.ensure_done().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -733,7 +733,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
|
|||
// Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked`
|
||||
// which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it
|
||||
// computes and caches its result.
|
||||
Some(hir::ConstContext::ConstFn) => tcx.ensure_with_value().mir_for_ctfe(did),
|
||||
Some(hir::ConstContext::ConstFn) => tcx.ensure_done().mir_for_ctfe(did),
|
||||
None => {}
|
||||
Some(other) => panic!("do not use `optimized_mir` for constants: {other:?}"),
|
||||
}
|
||||
|
|
@ -772,7 +772,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_
|
|||
}
|
||||
|
||||
if !tcx.is_synthetic_mir(def) {
|
||||
tcx.ensure_with_value().mir_borrowck(def);
|
||||
tcx.ensure_done().mir_borrowck(def);
|
||||
}
|
||||
let mut promoted = tcx.mir_promoted(def).1.steal();
|
||||
|
||||
|
|
|
|||
|
|
@ -1222,7 +1222,7 @@ fn collect_items_of_instance<'tcx>(
|
|||
mode: CollectionMode,
|
||||
) -> (MonoItems<'tcx>, MonoItems<'tcx>) {
|
||||
// This item is getting monomorphized, do mono-time checks.
|
||||
tcx.ensure().check_mono_item(instance);
|
||||
tcx.ensure_ok().check_mono_item(instance);
|
||||
|
||||
let body = tcx.instance_mir(instance.def);
|
||||
// Naively, in "used" collection mode, all functions get added to *both* `used_items` and
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use rustc_ast::MacroDef;
|
|||
use rustc_ast::visit::{VisitorResult, try_visit};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::{MultiSpan, listify};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::intravisit::{self, InferKind, Visitor};
|
||||
|
|
@ -958,29 +958,15 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
|
|||
// | ^^ field `gamma` is private # `fields.2` is `false`
|
||||
|
||||
// Get the list of all private fields for the main message.
|
||||
let field_names: Vec<_> = fields.iter().map(|(name, _, _)| name).collect();
|
||||
let field_names = match &field_names[..] {
|
||||
[] => return,
|
||||
[name] => format!("`{name}`"),
|
||||
[fields @ .., last] => format!(
|
||||
"{} and `{last}`",
|
||||
fields.iter().map(|f| format!("`{f}`")).collect::<Vec<_>>().join(", "),
|
||||
),
|
||||
};
|
||||
let Some(field_names) = listify(&fields[..], |(n, _, _)| format!("`{n}`")) else { return };
|
||||
let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into();
|
||||
|
||||
// Get the list of all private fields when pointing at the `..rest`.
|
||||
let rest_field_names: Vec<_> =
|
||||
fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect();
|
||||
let rest_len = rest_field_names.len();
|
||||
let rest_field_names = match &rest_field_names[..] {
|
||||
[] => String::new(),
|
||||
[name] => format!("`{name}`"),
|
||||
[fields @ .., last] => format!(
|
||||
"{} and `{last}`",
|
||||
fields.iter().map(|f| format!("`{f}`")).collect::<Vec<_>>().join(", "),
|
||||
),
|
||||
};
|
||||
let rest_field_names =
|
||||
listify(&rest_field_names[..], |n| format!("`{n}`")).unwrap_or_default();
|
||||
// Get all the labels for each field or `..rest` in the primary MultiSpan.
|
||||
let labels = fields
|
||||
.iter()
|
||||
|
|
@ -1005,7 +991,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
|
|||
} else {
|
||||
None
|
||||
},
|
||||
field_names: field_names.clone(),
|
||||
field_names,
|
||||
variant_descr: def.variant_descr(),
|
||||
def_path_str: self.tcx.def_path_str(def.did()),
|
||||
labels,
|
||||
|
|
|
|||
|
|
@ -435,7 +435,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||
terr: TypeError<'tcx>,
|
||||
param_env: Option<ParamEnv<'tcx>>,
|
||||
path: &mut Option<PathBuf>,
|
||||
) {
|
||||
match *cause.code() {
|
||||
ObligationCauseCode::Pattern {
|
||||
|
|
@ -458,7 +457,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
format!("this is an iterator with items of type `{}`", args.type_at(0)),
|
||||
);
|
||||
} else {
|
||||
let expected_ty = self.tcx.short_ty_string(expected_ty, path);
|
||||
let expected_ty = self.tcx.short_string(expected_ty, err.long_ty_path());
|
||||
err.span_label(span, format!("this expression has type `{expected_ty}`"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1545,7 +1544,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
(false, Mismatch::Fixed("existential projection"))
|
||||
}
|
||||
};
|
||||
let Some(vals) = self.values_str(values, cause) else {
|
||||
let Some(vals) = self.values_str(values, cause, diag.long_ty_path()) else {
|
||||
// Derived error. Cancel the emitter.
|
||||
// NOTE(eddyb) this was `.cancel()`, but `diag`
|
||||
// is borrowed, so we can't fully defuse it.
|
||||
|
|
@ -1600,9 +1599,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
if let Some((expected, found, p)) = expected_found {
|
||||
path = p;
|
||||
if let Some((expected, found)) = expected_found {
|
||||
let (expected_label, found_label, exp_found) = match exp_found {
|
||||
Mismatch::Variable(ef) => (
|
||||
ef.expected.prefix_string(self.tcx),
|
||||
|
|
@ -1878,11 +1875,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
// It reads better to have the error origin as the final
|
||||
// thing.
|
||||
self.note_error_origin(diag, cause, exp_found, terr, param_env, &mut path);
|
||||
if let Some(path) = path {
|
||||
diag.note(format!("the full type name has been written to '{}'", path.display()));
|
||||
diag.note("consider using `--verbose` to print the full type name to the console");
|
||||
}
|
||||
self.note_error_origin(diag, cause, exp_found, terr, param_env);
|
||||
|
||||
debug!(?diag);
|
||||
}
|
||||
|
|
@ -1891,6 +1884,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
trace: &TypeTrace<'tcx>,
|
||||
terr: TypeError<'tcx>,
|
||||
path: &mut Option<PathBuf>,
|
||||
) -> Vec<TypeErrorAdditionalDiags> {
|
||||
let mut suggestions = Vec::new();
|
||||
let span = trace.cause.span;
|
||||
|
|
@ -1969,7 +1963,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
})
|
||||
| ObligationCauseCode::BlockTailExpression(.., source)) = code
|
||||
&& let hir::MatchSource::TryDesugar(_) = source
|
||||
&& let Some((expected_ty, found_ty, _)) = self.values_str(trace.values, &trace.cause)
|
||||
&& let Some((expected_ty, found_ty)) = self.values_str(trace.values, &trace.cause, path)
|
||||
{
|
||||
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
|
||||
found: found_ty.content(),
|
||||
|
|
@ -2048,12 +2042,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
|
||||
|
||||
let span = trace.cause.span;
|
||||
let mut path = None;
|
||||
let failure_code = trace.cause.as_failure_code_diag(
|
||||
terr,
|
||||
span,
|
||||
self.type_error_additional_suggestions(&trace, terr),
|
||||
self.type_error_additional_suggestions(&trace, terr, &mut path),
|
||||
);
|
||||
let mut diag = self.dcx().create_err(failure_code);
|
||||
*diag.long_ty_path() = path;
|
||||
self.note_type_err(
|
||||
&mut diag,
|
||||
&trace.cause,
|
||||
|
|
@ -2098,10 +2094,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
values: ValuePairs<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
||||
file: &mut Option<PathBuf>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||
match values {
|
||||
ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found),
|
||||
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, file),
|
||||
ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
|
||||
ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
|
||||
|
|
@ -2111,7 +2108,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
found: exp_found.found.print_trait_sugared(),
|
||||
};
|
||||
match self.expected_found_str(pretty_exp_found) {
|
||||
Some((expected, found, _)) if expected == found => {
|
||||
Some((expected, found)) if expected == found => {
|
||||
self.expected_found_str(exp_found)
|
||||
}
|
||||
ret => ret,
|
||||
|
|
@ -2133,9 +2130,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
(None, None)
|
||||
};
|
||||
|
||||
let (exp, fnd) =
|
||||
self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2);
|
||||
Some((exp, fnd, None))
|
||||
Some(self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2143,7 +2138,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
fn expected_found_str_term(
|
||||
&self,
|
||||
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
||||
path: &mut Option<PathBuf>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
|
|
@ -2158,21 +2154,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let len = self.tcx.sess().diagnostic_width() + 40;
|
||||
let exp_s = exp.content();
|
||||
let fnd_s = fnd.content();
|
||||
let mut path = None;
|
||||
if exp_s.len() > len {
|
||||
let exp_s = self.tcx.short_ty_string(expected, &mut path);
|
||||
let exp_s = self.tcx.short_string(expected, path);
|
||||
exp = DiagStyledString::highlighted(exp_s);
|
||||
}
|
||||
if fnd_s.len() > len {
|
||||
let fnd_s = self.tcx.short_ty_string(found, &mut path);
|
||||
let fnd_s = self.tcx.short_string(found, path);
|
||||
fnd = DiagStyledString::highlighted(fnd_s);
|
||||
}
|
||||
(exp, fnd, path)
|
||||
(exp, fnd)
|
||||
}
|
||||
_ => (
|
||||
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
||||
DiagStyledString::highlighted(exp_found.found.to_string()),
|
||||
None,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
|
@ -2181,7 +2175,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
exp_found: ty::error::ExpectedFound<T>,
|
||||
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
|
||||
) -> Option<(DiagStyledString, DiagStyledString)> {
|
||||
let exp_found = self.resolve_vars_if_possible(exp_found);
|
||||
if exp_found.references_error() {
|
||||
return None;
|
||||
|
|
@ -2190,7 +2184,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
Some((
|
||||
DiagStyledString::highlighted(exp_found.expected.to_string()),
|
||||
DiagStyledString::highlighted(exp_found.found.to_string()),
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -713,7 +713,7 @@ impl<'tcx> InferSourceKind<'tcx> {
|
|||
if ty.is_closure() {
|
||||
("closure", closure_as_fn_str(infcx, ty), path)
|
||||
} else if !ty.is_ty_or_numeric_infer() {
|
||||
("normal", infcx.tcx.short_ty_string(ty, &mut path), path)
|
||||
("normal", infcx.tcx.short_string(ty, &mut path), path)
|
||||
} else {
|
||||
("other", String::new(), path)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,422 +0,0 @@
|
|||
use rustc_errors::{Diag, Subdiagnostic};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{self, IsSuggestable, Region, Ty};
|
||||
use rustc_span::kw;
|
||||
use tracing::debug;
|
||||
|
||||
use super::ObligationCauseAsDiagArg;
|
||||
use crate::error_reporting::infer::{TypeErrCtxt, note_and_explain_region};
|
||||
use crate::errors::{
|
||||
FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData,
|
||||
RegionOriginNote, WhereClauseSuggestions, note_and_explain,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::infer::{self, SubregionOrigin};
|
||||
|
||||
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
|
||||
match *origin {
|
||||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
||||
span: trace.cause.span,
|
||||
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
||||
expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
|
||||
}
|
||||
.add_to_diag(err),
|
||||
infer::Reborrow(span) => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
|
||||
}
|
||||
infer::RelateObjectBound(span) => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
|
||||
.add_to_diag(err);
|
||||
}
|
||||
infer::ReferenceOutlivesReferent(ty, span) => {
|
||||
RegionOriginNote::WithName {
|
||||
span,
|
||||
msg: fluent::infer_reference_outlives_referent,
|
||||
name: &self.ty_to_string(ty),
|
||||
continues: false,
|
||||
}
|
||||
.add_to_diag(err);
|
||||
}
|
||||
infer::RelateParamBound(span, ty, opt_span) => {
|
||||
RegionOriginNote::WithName {
|
||||
span,
|
||||
msg: fluent::infer_relate_param_bound,
|
||||
name: &self.ty_to_string(ty),
|
||||
continues: opt_span.is_some(),
|
||||
}
|
||||
.add_to_diag(err);
|
||||
if let Some(span) = opt_span {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
|
||||
.add_to_diag(err);
|
||||
}
|
||||
}
|
||||
infer::RelateRegionParamBound(span, _) => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
|
||||
.add_to_diag(err);
|
||||
}
|
||||
infer::CompareImplItemObligation { span, .. } => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
|
||||
.add_to_diag(err);
|
||||
}
|
||||
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
|
||||
self.note_region_origin(err, parent);
|
||||
}
|
||||
infer::AscribeUserTypeProvePredicate(span) => {
|
||||
RegionOriginNote::Plain {
|
||||
span,
|
||||
msg: fluent::infer_ascribe_user_type_prove_predicate,
|
||||
}
|
||||
.add_to_diag(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn report_concrete_failure(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
let mut err = match origin {
|
||||
infer::Subtype(box trace) => {
|
||||
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
|
||||
let mut err = self.report_and_explain_type_error(trace, terr);
|
||||
match (*sub, *sup) {
|
||||
(ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
|
||||
(ty::RePlaceholder(_), _) => {
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"",
|
||||
sup,
|
||||
" doesn't meet the lifetime requirements",
|
||||
None,
|
||||
);
|
||||
}
|
||||
(_, ty::RePlaceholder(_)) => {
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"the required lifetime does not necessarily outlive ",
|
||||
sub,
|
||||
"",
|
||||
None,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"",
|
||||
sup,
|
||||
"...",
|
||||
None,
|
||||
);
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
generic_param_scope,
|
||||
"...does not necessarily outlive ",
|
||||
sub,
|
||||
"",
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
err
|
||||
}
|
||||
infer::Reborrow(span) => {
|
||||
let reference_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::RefValidFor,
|
||||
note_and_explain::SuffixKind::Continues,
|
||||
);
|
||||
let content_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::ContentValidFor,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
self.dcx().create_err(OutlivesContent {
|
||||
span,
|
||||
notes: reference_valid.into_iter().chain(content_valid).collect(),
|
||||
})
|
||||
}
|
||||
infer::RelateObjectBound(span) => {
|
||||
let object_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::TypeObjValidFor,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
let pointer_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::SourcePointerValidFor,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
self.dcx().create_err(OutlivesBound {
|
||||
span,
|
||||
notes: object_valid.into_iter().chain(pointer_valid).collect(),
|
||||
})
|
||||
}
|
||||
infer::RelateParamBound(span, ty, opt_span) => {
|
||||
let prefix = match *sub {
|
||||
ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
|
||||
_ => note_and_explain::PrefixKind::TypeOutlive,
|
||||
};
|
||||
let suffix = if opt_span.is_some() {
|
||||
note_and_explain::SuffixKind::ReqByBinding
|
||||
} else {
|
||||
note_and_explain::SuffixKind::Empty
|
||||
};
|
||||
let note = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
opt_span,
|
||||
prefix,
|
||||
suffix,
|
||||
);
|
||||
self.dcx().create_err(FulfillReqLifetime {
|
||||
span,
|
||||
ty: self.resolve_vars_if_possible(ty),
|
||||
note,
|
||||
})
|
||||
}
|
||||
infer::RelateRegionParamBound(span, _) => {
|
||||
let param_instantiated = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfParamInstantiatedWith,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
let param_must_outlive = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfParamMustOutlive,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
self.dcx().create_err(LfBoundNotSatisfied {
|
||||
span,
|
||||
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
|
||||
})
|
||||
}
|
||||
infer::ReferenceOutlivesReferent(ty, span) => {
|
||||
let pointer_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::PointerValidFor,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
let data_valid = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::DataValidFor,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
self.dcx().create_err(RefLongerThanData {
|
||||
span,
|
||||
ty: self.resolve_vars_if_possible(ty),
|
||||
notes: pointer_valid.into_iter().chain(data_valid).collect(),
|
||||
})
|
||||
}
|
||||
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
|
||||
let mut err = self.infcx.report_extra_impl_obligation(
|
||||
span,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
&format!("`{sup}: {sub}`"),
|
||||
);
|
||||
// We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
|
||||
if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id)
|
||||
&& generics.where_clause_span.contains(span)
|
||||
{
|
||||
self.suggest_copy_trait_method_bounds(
|
||||
trait_item_def_id,
|
||||
impl_item_def_id,
|
||||
&mut err,
|
||||
);
|
||||
}
|
||||
err
|
||||
}
|
||||
infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
|
||||
let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup);
|
||||
|
||||
// Don't mention the item name if it's an RPITIT, since that'll just confuse
|
||||
// folks.
|
||||
if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) {
|
||||
let trait_item_span = self.tcx.def_span(trait_item_def_id);
|
||||
let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
|
||||
err.span_label(
|
||||
trait_item_span,
|
||||
format!("definition of `{item_name}` from trait"),
|
||||
);
|
||||
}
|
||||
|
||||
self.suggest_copy_trait_method_bounds(
|
||||
trait_item_def_id,
|
||||
impl_item_def_id,
|
||||
&mut err,
|
||||
);
|
||||
err
|
||||
}
|
||||
infer::AscribeUserTypeProvePredicate(span) => {
|
||||
let instantiated = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sup,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfInstantiatedWith,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
let must_outlive = note_and_explain::RegionExplanation::new(
|
||||
self.tcx,
|
||||
generic_param_scope,
|
||||
sub,
|
||||
None,
|
||||
note_and_explain::PrefixKind::LfMustOutlive,
|
||||
note_and_explain::SuffixKind::Empty,
|
||||
);
|
||||
self.dcx().create_err(LfBoundNotSatisfied {
|
||||
span,
|
||||
notes: instantiated.into_iter().chain(must_outlive).collect(),
|
||||
})
|
||||
}
|
||||
};
|
||||
if sub.is_error() || sup.is_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
pub fn suggest_copy_trait_method_bounds(
|
||||
&self,
|
||||
trait_item_def_id: DefId,
|
||||
impl_item_def_id: LocalDefId,
|
||||
err: &mut Diag<'_>,
|
||||
) {
|
||||
// FIXME(compiler-errors): Right now this is only being used for region
|
||||
// predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
|
||||
// but right now it's not really very smart when it comes to implicit `Sized`
|
||||
// predicates and bounds on the trait itself.
|
||||
|
||||
let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
|
||||
return;
|
||||
};
|
||||
let trait_args = trait_ref
|
||||
.instantiate_identity()
|
||||
// Replace the explicit self type with `Self` for better suggestion rendering
|
||||
.with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper))
|
||||
.args;
|
||||
let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id)
|
||||
.rebase_onto(self.tcx, impl_def_id, trait_args);
|
||||
|
||||
let Ok(trait_predicates) =
|
||||
self.tcx
|
||||
.explicit_predicates_of(trait_item_def_id)
|
||||
.instantiate_own(self.tcx, trait_item_args)
|
||||
.map(|(pred, _)| {
|
||||
if pred.is_suggestable(self.tcx, false) {
|
||||
Ok(pred.to_string())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, ()>>()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let suggestion = if trait_predicates.is_empty() {
|
||||
WhereClauseSuggestions::Remove { span: generics.where_clause_span }
|
||||
} else {
|
||||
let space = if generics.where_clause_span.is_empty() { " " } else { "" };
|
||||
WhereClauseSuggestions::CopyPredicates {
|
||||
span: generics.where_clause_span,
|
||||
space,
|
||||
trait_predicates: trait_predicates.join(", "),
|
||||
}
|
||||
};
|
||||
err.subdiagnostic(suggestion);
|
||||
}
|
||||
|
||||
pub(super) fn report_placeholder_failure(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
placeholder_origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
// I can't think how to do better than this right now. -nikomatsakis
|
||||
debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
|
||||
match placeholder_origin {
|
||||
infer::Subtype(box ref trace)
|
||||
if matches!(
|
||||
&trace.cause.code().peel_derives(),
|
||||
ObligationCauseCode::WhereClause(..)
|
||||
| ObligationCauseCode::WhereClauseInExpr(..)
|
||||
) =>
|
||||
{
|
||||
// Hack to get around the borrow checker because trace.cause has an `Rc`.
|
||||
if let ObligationCauseCode::WhereClause(_, span)
|
||||
| ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
|
||||
&trace.cause.code().peel_derives()
|
||||
&& !span.is_dummy()
|
||||
{
|
||||
let span = *span;
|
||||
self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
|
||||
.with_span_note(span, "the lifetime requirement is introduced here")
|
||||
} else {
|
||||
unreachable!(
|
||||
"control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
|
||||
)
|
||||
}
|
||||
}
|
||||
infer::Subtype(box trace) => {
|
||||
let terr = TypeError::RegionsPlaceholderMismatch;
|
||||
return self.report_and_explain_type_error(trace, terr);
|
||||
}
|
||||
_ => {
|
||||
return self.report_concrete_failure(
|
||||
generic_param_scope,
|
||||
placeholder_origin,
|
||||
sub,
|
||||
sup,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -221,7 +221,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
|
||||
span: trace.cause.span,
|
||||
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
|
||||
expected_found: self.values_str(trace.values, &trace.cause).map(|(e, f, _)| (e, f)),
|
||||
expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()),
|
||||
}
|
||||
.add_to_diag(err),
|
||||
infer::Reborrow(span) => {
|
||||
|
|
@ -946,10 +946,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
if let infer::Subtype(ref sup_trace) = sup_origin
|
||||
&& let infer::Subtype(ref sub_trace) = sub_origin
|
||||
&& let Some((sup_expected, sup_found, _)) =
|
||||
self.values_str(sup_trace.values, &sup_trace.cause)
|
||||
&& let Some((sub_expected, sub_found, _)) =
|
||||
self.values_str(sub_trace.values, &sup_trace.cause)
|
||||
&& let Some((sup_expected, sup_found)) =
|
||||
self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path())
|
||||
&& let Some((sub_expected, sub_found)) =
|
||||
self.values_str(sub_trace.values, &sup_trace.cause, err.long_ty_path())
|
||||
&& sub_expected == sup_expected
|
||||
&& sub_found == sup_found
|
||||
{
|
||||
|
|
|
|||
|
|
@ -418,7 +418,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
};
|
||||
|
||||
let sugg = match (expected.is_ref(), found.is_ref()) {
|
||||
(true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
|
||||
(true, false) => {
|
||||
FunctionPointerSuggestion::UseRef { span: span.shrink_to_lo() }
|
||||
}
|
||||
(false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
|
||||
(true, true) => {
|
||||
diag.subdiagnostic(FnItemsAreDistinct);
|
||||
|
|
@ -426,7 +428,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
(false, false) => {
|
||||
diag.subdiagnostic(FnItemsAreDistinct);
|
||||
FunctionPointerSuggestion::Cast { span, fn_name, sig }
|
||||
FunctionPointerSuggestion::Cast { span: span.shrink_to_hi(), sig }
|
||||
}
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
|
|
@ -466,8 +468,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
} else {
|
||||
FunctionPointerSuggestion::CastBoth {
|
||||
span,
|
||||
fn_name,
|
||||
span: span.shrink_to_hi(),
|
||||
found_sig: *found_sig,
|
||||
expected_sig: *expected_sig,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
let predicate = self.resolve_vars_if_possible(obligation.predicate);
|
||||
let span = obligation.cause.span;
|
||||
let mut file = None;
|
||||
|
||||
debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
|
||||
|
||||
|
|
@ -179,7 +180,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return e;
|
||||
}
|
||||
|
||||
if let Err(guar) = self.tcx.ensure().coherent_trait(trait_pred.def_id()) {
|
||||
if let Err(guar) = self.tcx.ensure_ok().coherent_trait(trait_pred.def_id()) {
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
return guar;
|
||||
|
|
@ -245,7 +246,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
span,
|
||||
E0283,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
self.tcx.short_string(predicate, &mut file),
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -292,7 +293,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
err.cancel();
|
||||
return e;
|
||||
}
|
||||
err.note(format!("cannot satisfy `{predicate}`"));
|
||||
let pred = self.tcx.short_string(predicate, &mut file);
|
||||
err.note(format!("cannot satisfy `{pred}`"));
|
||||
let impl_candidates =
|
||||
self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
|
||||
if impl_candidates.len() < 40 {
|
||||
|
|
@ -511,8 +513,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return e;
|
||||
}
|
||||
|
||||
if let Err(guar) =
|
||||
self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_term.def_id))
|
||||
if let Err(guar) = self
|
||||
.tcx
|
||||
.ensure_ok()
|
||||
.coherent_trait(self.tcx.parent(data.projection_term.def_id))
|
||||
{
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
|
|
@ -524,6 +528,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
.iter()
|
||||
.chain(Some(data.term.into_arg()))
|
||||
.find(|g| g.has_non_region_infer());
|
||||
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||
if let Some(arg) = arg {
|
||||
self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
|
|
@ -539,8 +544,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
self.dcx(),
|
||||
span,
|
||||
E0284,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
"type annotations needed: cannot satisfy `{predicate}`",
|
||||
)
|
||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||
}
|
||||
|
|
@ -565,12 +569,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
err
|
||||
} else {
|
||||
// If we can't find a generic parameter, just print a generic error
|
||||
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0284,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
"type annotations needed: cannot satisfy `{predicate}`",
|
||||
)
|
||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||
}
|
||||
|
|
@ -590,6 +594,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
let alias = self.tcx.short_string(alias, &mut file);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
|
|
@ -603,16 +608,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
let predicate = self.tcx.short_string(predicate, &mut file);
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0284,
|
||||
"type annotations needed: cannot satisfy `{}`",
|
||||
predicate,
|
||||
"type annotations needed: cannot satisfy `{predicate}`",
|
||||
)
|
||||
.with_span_label(span, format!("cannot satisfy `{predicate}`"))
|
||||
}
|
||||
};
|
||||
*err.long_ty_path() = file;
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use core::ops::ControlFlow;
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_ast::TraitObjectSyntax;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
|
@ -9,7 +10,6 @@ use rustc_errors::{
|
|||
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions,
|
||||
pluralize, struct_span_code_err,
|
||||
};
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{self as hir, LangItem, Node};
|
||||
|
|
@ -20,8 +20,8 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
|||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::print::{
|
||||
FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _,
|
||||
PrintTraitRefExt as _, with_forced_trimmed_paths,
|
||||
PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _,
|
||||
with_forced_trimmed_paths,
|
||||
};
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
|
@ -60,6 +60,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
) -> ErrorGuaranteed {
|
||||
let tcx = self.tcx;
|
||||
let mut span = obligation.cause.span;
|
||||
let mut long_ty_file = None;
|
||||
|
||||
let mut err = match *error {
|
||||
SelectionError::Unimplemented => {
|
||||
|
|
@ -169,11 +170,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let Err(guar) = self.fn_arg_obligation(&obligation) {
|
||||
return guar;
|
||||
}
|
||||
let mut file = None;
|
||||
let (post_message, pre_message, type_def) = self
|
||||
.get_parent_trait_ref(obligation.cause.code())
|
||||
.map(|(t, s)| {
|
||||
let t = self.tcx.short_ty_string(t, &mut file);
|
||||
let t = self.tcx.short_string(t, &mut long_ty_file);
|
||||
(
|
||||
format!(" in `{t}`"),
|
||||
format!("within `{t}`, "),
|
||||
|
|
@ -181,12 +181,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let file_note = file.as_ref().map(|file| format!(
|
||||
"the full trait has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
|
||||
let mut long_ty_file = None;
|
||||
|
||||
let OnUnimplementedNote {
|
||||
message,
|
||||
|
|
@ -223,6 +217,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
None,
|
||||
append_const_msg,
|
||||
post_message,
|
||||
&mut long_ty_file,
|
||||
);
|
||||
|
||||
let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)
|
||||
|
|
@ -251,14 +246,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
||||
*err.long_ty_path() = long_ty_file;
|
||||
|
||||
if let Some(long_ty_file) = long_ty_file {
|
||||
err.note(format!(
|
||||
"the full name for the type has been written to '{}'",
|
||||
long_ty_file.display(),
|
||||
));
|
||||
err.note("consider using `--verbose` to print the full type name to the console");
|
||||
}
|
||||
let mut suggested = false;
|
||||
if is_try_conversion {
|
||||
suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err);
|
||||
|
|
@ -309,7 +298,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
return err.emit();
|
||||
}
|
||||
|
||||
file_note.map(|note| err.note(note));
|
||||
if let Some(s) = label {
|
||||
// If it has a custom `#[rustc_on_unimplemented]`
|
||||
// error message, let's display it as the label!
|
||||
|
|
@ -762,14 +750,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
trait_ref: predicate.trait_ref,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
});
|
||||
let mut file = None;
|
||||
let err_msg = self.get_standard_error_message(
|
||||
trait_ref,
|
||||
None,
|
||||
Some(predicate.constness()),
|
||||
None,
|
||||
String::new(),
|
||||
&mut file,
|
||||
);
|
||||
let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
||||
*diag.long_ty_path() = file;
|
||||
if !self.predicate_may_hold(&Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
|
|
@ -1381,6 +1372,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
_ => (None, error.err),
|
||||
};
|
||||
|
||||
let mut file = None;
|
||||
let (msg, span, closure_span) = values
|
||||
.and_then(|(predicate, normalized_term, expected_term)| {
|
||||
self.maybe_detailed_projection_msg(
|
||||
|
|
@ -1388,24 +1380,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
predicate,
|
||||
normalized_term,
|
||||
expected_term,
|
||||
&mut file,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let mut cx = FmtPrinter::new_with_limit(
|
||||
self.tcx,
|
||||
Namespace::TypeNS,
|
||||
rustc_session::Limit(10),
|
||||
);
|
||||
(
|
||||
with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
|
||||
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
|
||||
cx.into_buffer()
|
||||
})),
|
||||
with_forced_trimmed_paths!(format!(
|
||||
"type mismatch resolving `{}`",
|
||||
self.tcx
|
||||
.short_string(self.resolve_vars_if_possible(predicate), &mut file),
|
||||
)),
|
||||
obligation.cause.span,
|
||||
None,
|
||||
)
|
||||
});
|
||||
let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");
|
||||
*diag.long_ty_path() = file;
|
||||
if let Some(span) = closure_span {
|
||||
// Mark the closure decl so that it is seen even if we are pointing at the return
|
||||
// type or expression.
|
||||
|
|
@ -1471,15 +1461,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
ty.span,
|
||||
with_forced_trimmed_paths!(Cow::from(format!(
|
||||
"type mismatch resolving `{}`",
|
||||
{
|
||||
let mut cx = FmtPrinter::new_with_limit(
|
||||
self.tcx,
|
||||
Namespace::TypeNS,
|
||||
rustc_session::Limit(5),
|
||||
);
|
||||
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
|
||||
cx.into_buffer()
|
||||
}
|
||||
self.tcx.short_string(
|
||||
self.resolve_vars_if_possible(predicate),
|
||||
diag.long_ty_path()
|
||||
),
|
||||
))),
|
||||
true,
|
||||
)),
|
||||
|
|
@ -1512,6 +1497,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
projection_term: ty::AliasTerm<'tcx>,
|
||||
normalized_ty: ty::Term<'tcx>,
|
||||
expected_ty: ty::Term<'tcx>,
|
||||
file: &mut Option<PathBuf>,
|
||||
) -> Option<(String, Span, Option<Span>)> {
|
||||
let trait_def_id = projection_term.trait_def_id(self.tcx);
|
||||
let self_ty = projection_term.self_ty();
|
||||
|
|
@ -1552,7 +1538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
let item = match self_ty.kind() {
|
||||
ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
|
||||
_ => self_ty.to_string(),
|
||||
_ => self.tcx.short_string(self_ty, file),
|
||||
};
|
||||
Some((format!(
|
||||
"expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
|
||||
|
|
@ -1984,8 +1970,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
StringPart::normal(" implemented for `"),
|
||||
]);
|
||||
if types_content.0 == types_content.1 {
|
||||
let ty =
|
||||
self.tcx.short_ty_string(obligation_trait_ref.self_ty(), &mut None);
|
||||
let ty = self
|
||||
.tcx
|
||||
.short_string(obligation_trait_ref.self_ty(), err.long_ty_path());
|
||||
msg.push(StringPart::normal(ty));
|
||||
} else {
|
||||
msg.extend(types.0.0);
|
||||
|
|
@ -2342,7 +2329,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// First, attempt to add note to this error with an async-await-specific
|
||||
// message, and fall back to regular note otherwise.
|
||||
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
|
|
@ -2351,15 +2337,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
obligation.cause.code(),
|
||||
&mut vec![],
|
||||
&mut Default::default(),
|
||||
&mut long_ty_file,
|
||||
);
|
||||
if let Some(file) = long_ty_file {
|
||||
err.note(format!(
|
||||
"the full name for the type has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
err.note("consider using `--verbose` to print the full type name to the console");
|
||||
}
|
||||
self.suggest_unsized_bound_if_applicable(err, obligation);
|
||||
if let Some(span) = err.span.primary_span()
|
||||
&& let Some(mut diag) =
|
||||
|
|
@ -2403,6 +2381,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
predicate_constness: Option<ty::BoundConstness>,
|
||||
append_const_msg: Option<AppendConstMessage>,
|
||||
post_message: String,
|
||||
long_ty_file: &mut Option<PathBuf>,
|
||||
) -> String {
|
||||
message
|
||||
.and_then(|cannot_do_this| {
|
||||
|
|
@ -2426,7 +2405,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
.unwrap_or_else(|| {
|
||||
format!(
|
||||
"the trait bound `{}` is not satisfied{post_message}",
|
||||
trait_predicate.print_with_bound_constness(predicate_constness)
|
||||
self.tcx.short_string(
|
||||
trait_predicate.print_with_bound_constness(predicate_constness),
|
||||
long_ty_file,
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
if let ObligationCauseCode::WhereClause(..)
|
||||
| ObligationCauseCode::WhereClauseInExpr(..) = code
|
||||
{
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
error.obligation.cause.body_id,
|
||||
&mut diag,
|
||||
|
|
@ -315,17 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
code,
|
||||
&mut vec![],
|
||||
&mut Default::default(),
|
||||
&mut long_ty_file,
|
||||
);
|
||||
if let Some(file) = long_ty_file {
|
||||
diag.note(format!(
|
||||
"the full name for the type has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
diag.note(
|
||||
"consider using `--verbose` to print the full type name to the console",
|
||||
);
|
||||
}
|
||||
}
|
||||
diag.emit()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@ impl<'tcx> OnUnimplementedFormatString {
|
|||
let value = match param.kind {
|
||||
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||
if let Some(ty) = trait_ref.args[param.index as usize].as_type() {
|
||||
tcx.short_ty_string(ty, long_ty_file)
|
||||
tcx.short_string(ty, long_ty_file)
|
||||
} else {
|
||||
trait_ref.args[param.index as usize].to_string()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
obligation.cause.span,
|
||||
suggest_increasing_limit,
|
||||
|err| {
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
|
|
@ -150,17 +149,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
obligation.cause.code(),
|
||||
&mut vec![],
|
||||
&mut Default::default(),
|
||||
&mut long_ty_file,
|
||||
);
|
||||
if let Some(file) = long_ty_file {
|
||||
err.note(format!(
|
||||
"the full name for the type has been written to '{}'",
|
||||
file.display(),
|
||||
));
|
||||
err.note(
|
||||
"consider using `--verbose` to print the full type name to the console",
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
use std::assert_matches::debug_assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use rustc_abi::ExternAbi;
|
||||
|
|
@ -1297,30 +1296,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// Because of this, we modify the error to refer to the original obligation and
|
||||
// return early in the caller.
|
||||
|
||||
let msg = format!("the trait bound `{old_pred}` is not satisfied");
|
||||
let msg = format!(
|
||||
"the trait bound `{}` is not satisfied",
|
||||
self.tcx.short_string(old_pred, err.long_ty_path()),
|
||||
);
|
||||
let self_ty_str =
|
||||
self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path());
|
||||
if has_custom_message {
|
||||
err.note(msg);
|
||||
} else {
|
||||
err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
|
||||
}
|
||||
let mut file = None;
|
||||
err.span_label(
|
||||
span,
|
||||
format!(
|
||||
"the trait `{}` is not implemented for `{}`",
|
||||
old_pred.print_modifiers_and_trait_path(),
|
||||
self.tcx.short_ty_string(old_pred.self_ty().skip_binder(), &mut file),
|
||||
"the trait `{}` is not implemented for `{self_ty_str}`",
|
||||
old_pred.print_modifiers_and_trait_path()
|
||||
),
|
||||
);
|
||||
if let Some(file) = file {
|
||||
err.note(format!(
|
||||
"the full type name has been written to '{}'",
|
||||
file.display()
|
||||
));
|
||||
err.note(
|
||||
"consider using `--verbose` to print full type name to the console",
|
||||
);
|
||||
}
|
||||
|
||||
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
|
||||
err.span_suggestions(
|
||||
|
|
@ -2689,7 +2682,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// Add a note for the item obligation that remains - normally a note pointing to the
|
||||
// bound that introduced the obligation (e.g. `T: Send`).
|
||||
debug!(?next_code);
|
||||
let mut long_ty_file = None;
|
||||
self.note_obligation_cause_code(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
|
|
@ -2698,7 +2690,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
next_code.unwrap(),
|
||||
&mut Vec::new(),
|
||||
&mut Default::default(),
|
||||
&mut long_ty_file,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2711,7 +2702,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
cause_code: &ObligationCauseCode<'tcx>,
|
||||
obligated_types: &mut Vec<Ty<'tcx>>,
|
||||
seen_requirements: &mut FxHashSet<DefId>,
|
||||
long_ty_file: &mut Option<PathBuf>,
|
||||
) where
|
||||
T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
|
||||
{
|
||||
|
|
@ -2965,9 +2955,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
ObligationCauseCode::Coercion { source, target } => {
|
||||
let source =
|
||||
tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
|
||||
tcx.short_string(self.resolve_vars_if_possible(source), err.long_ty_path());
|
||||
let target =
|
||||
tcx.short_ty_string(self.resolve_vars_if_possible(target), long_ty_file);
|
||||
tcx.short_string(self.resolve_vars_if_possible(target), err.long_ty_path());
|
||||
err.note(with_forced_trimmed_paths!(format!(
|
||||
"required for the cast from `{source}` to `{target}`",
|
||||
)));
|
||||
|
|
@ -3252,7 +3242,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if !is_upvar_tys_infer_tuple {
|
||||
let ty_str = tcx.short_ty_string(ty, long_ty_file);
|
||||
let ty_str = tcx.short_string(ty, err.long_ty_path());
|
||||
let msg = format!("required because it appears within the type `{ty_str}`");
|
||||
match ty.kind() {
|
||||
ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
|
||||
|
|
@ -3330,7 +3320,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
} else {
|
||||
|
|
@ -3343,7 +3332,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
cause_code.peel_derives(),
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -3353,7 +3341,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
|
||||
let parent_def_id = parent_trait_pred.def_id();
|
||||
let self_ty_str =
|
||||
tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
|
||||
tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
|
||||
let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
|
||||
let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
|
||||
let mut is_auto_trait = false;
|
||||
|
|
@ -3449,8 +3437,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
count,
|
||||
pluralize!(count)
|
||||
));
|
||||
let self_ty = tcx
|
||||
.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
|
||||
let self_ty = tcx.short_string(
|
||||
parent_trait_pred.skip_binder().self_ty(),
|
||||
err.long_ty_path(),
|
||||
);
|
||||
err.note(format!(
|
||||
"required for `{self_ty}` to implement `{}`",
|
||||
parent_trait_pred.print_modifiers_and_trait_path()
|
||||
|
|
@ -3466,7 +3456,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -3505,7 +3494,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.derived.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -3519,7 +3507,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -3536,7 +3523,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -3551,7 +3537,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
nested,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
let mut multispan = MultiSpan::from(span);
|
||||
|
|
@ -3582,7 +3567,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -3622,7 +3606,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
ObligationCauseCode::OpaqueReturnType(expr_info) => {
|
||||
let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
|
||||
let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file);
|
||||
let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
|
||||
let expr = tcx.hir().expect_expr(hir_id);
|
||||
(expr_ty, expr)
|
||||
} else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
|
||||
|
|
@ -3637,7 +3621,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&& let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
|
||||
&& self.can_eq(param_env, pred.self_ty(), expr_ty)
|
||||
{
|
||||
let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file);
|
||||
let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
|
||||
(expr_ty, expr)
|
||||
} else {
|
||||
return;
|
||||
|
|
@ -5231,7 +5215,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
|
|||
format!(
|
||||
"{pre_message}the trait `{}` is not implemented for{desc} `{}`",
|
||||
trait_predicate.print_modifiers_and_trait_path(),
|
||||
tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
|
||||
tcx.short_string(trait_predicate.self_ty().skip_binder(), &mut None),
|
||||
)
|
||||
} else {
|
||||
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
|
||||
|
|
|
|||
|
|
@ -1391,15 +1391,13 @@ pub struct OpaqueCapturesLifetime<'tcx> {
|
|||
pub enum FunctionPointerSuggestion<'a> {
|
||||
#[suggestion(
|
||||
trait_selection_fps_use_ref,
|
||||
code = "&{fn_name}",
|
||||
code = "&",
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
UseRef {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
#[skip_arg]
|
||||
fn_name: String,
|
||||
},
|
||||
#[suggestion(
|
||||
trait_selection_fps_remove_ref,
|
||||
|
|
@ -1429,7 +1427,7 @@ pub enum FunctionPointerSuggestion<'a> {
|
|||
},
|
||||
#[suggestion(
|
||||
trait_selection_fps_cast,
|
||||
code = "{fn_name} as {sig}",
|
||||
code = " as {sig}",
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
|
|
@ -1437,13 +1435,11 @@ pub enum FunctionPointerSuggestion<'a> {
|
|||
#[primary_span]
|
||||
span: Span,
|
||||
#[skip_arg]
|
||||
fn_name: String,
|
||||
#[skip_arg]
|
||||
sig: Binder<'a, FnSig<'a>>,
|
||||
},
|
||||
#[suggestion(
|
||||
trait_selection_fps_cast_both,
|
||||
code = "{fn_name} as {found_sig}",
|
||||
code = " as {found_sig}",
|
||||
style = "hidden",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
|
|
@ -1451,8 +1447,6 @@ pub enum FunctionPointerSuggestion<'a> {
|
|||
#[primary_span]
|
||||
span: Span,
|
||||
#[skip_arg]
|
||||
fn_name: String,
|
||||
#[skip_arg]
|
||||
found_sig: Binder<'a, FnSig<'a>>,
|
||||
expected_sig: Binder<'a, FnSig<'a>>,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ fn report_conflicting_impls<'tcx>(
|
|||
match used_to_be_allowed {
|
||||
None => {
|
||||
let reported = if overlap.with_impl.is_local()
|
||||
|| tcx.ensure().orphan_check_impl(impl_def_id).is_ok()
|
||||
|| tcx.ensure_ok().orphan_check_impl(impl_def_id).is_ok()
|
||||
{
|
||||
let mut err = tcx.dcx().struct_span_err(impl_span, msg());
|
||||
err.code(E0119);
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ pub(crate) fn assoc_def(
|
|||
// Ensure that the impl is constrained, otherwise projection may give us
|
||||
// bad unconstrained infer vars.
|
||||
if let Some(impl_def_id) = impl_def_id.as_local() {
|
||||
tcx.ensure().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?;
|
||||
tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?;
|
||||
}
|
||||
|
||||
let item = tcx.associated_item(impl_item_id);
|
||||
|
|
@ -402,7 +402,7 @@ pub(crate) fn assoc_def(
|
|||
if assoc_item.item.container == ty::AssocItemContainer::Impl
|
||||
&& let Some(impl_def_id) = assoc_item.item.container_id(tcx).as_local()
|
||||
{
|
||||
tcx.ensure().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?;
|
||||
tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?;
|
||||
}
|
||||
|
||||
Ok(assoc_item)
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ fn resolve_associated_item<'tcx>(
|
|||
if trait_item_id != leaf_def.item.def_id
|
||||
&& let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
|
||||
{
|
||||
tcx.ensure().compare_impl_item(leaf_def_item)?;
|
||||
tcx.ensure_ok().compare_impl_item(leaf_def_item)?;
|
||||
}
|
||||
|
||||
Some(ty::Instance::new(leaf_def.item.def_id, args))
|
||||
|
|
|
|||
|
|
@ -2318,14 +2318,10 @@ pub fn exit(code: i32) -> ! {
|
|||
/// Terminates the process in an abnormal fashion.
|
||||
///
|
||||
/// The function will never return and will immediately terminate the current
|
||||
/// process in a platform specific "abnormal" manner.
|
||||
///
|
||||
/// Note that because this function never returns, and that it terminates the
|
||||
/// process, no destructors on the current stack or any other thread's stack
|
||||
/// will be run.
|
||||
///
|
||||
/// Rust IO buffers (eg, from `BufWriter`) will not be flushed.
|
||||
/// Likewise, C stdio buffers will (on most platforms) not be flushed.
|
||||
/// process in a platform specific "abnormal" manner. As a consequence,
|
||||
/// no destructors on the current stack or any other thread's stack
|
||||
/// will be run, Rust IO buffers (eg, from `BufWriter`) will not be flushed,
|
||||
/// and C stdio buffers will (on most platforms) not be flushed.
|
||||
///
|
||||
/// This is in contrast to the default behavior of [`panic!`] which unwinds
|
||||
/// the current thread's stack and calls all destructors.
|
||||
|
|
|
|||
|
|
@ -525,8 +525,7 @@ auto:
|
|||
env:
|
||||
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
|
||||
SCRIPT: make ci-mingw
|
||||
# We are intentionally allowing an old toolchain on this builder (and that's
|
||||
# incompatible with LLVM downloads today).
|
||||
# There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
<<: *job-windows-25-8c
|
||||
|
||||
|
|
@ -535,8 +534,7 @@ auto:
|
|||
env:
|
||||
SCRIPT: make ci-mingw-x
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
|
||||
# We are intentionally allowing an old toolchain on this builder (and that's
|
||||
# incompatible with LLVM downloads today).
|
||||
# There is no dist-x86_64-mingw-alt, so there is no prebuilt LLVM with assertions
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
<<: *job-windows
|
||||
|
||||
|
|
@ -544,8 +542,7 @@ auto:
|
|||
env:
|
||||
SCRIPT: make ci-mingw-bootstrap
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
|
||||
# We are intentionally allowing an old toolchain on this builder (and that's
|
||||
# incompatible with LLVM downloads today).
|
||||
# There is no dist-x86_64-mingw-alt, so there is no prebuilt LLVM with assertions
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
<<: *job-windows
|
||||
|
||||
|
|
@ -593,9 +590,6 @@ auto:
|
|||
RUST_CONFIGURE_ARGS: >-
|
||||
--build=i686-pc-windows-gnu
|
||||
--enable-full-tools
|
||||
# We are intentionally allowing an old toolchain on this builder (and that's
|
||||
# incompatible with LLVM downloads today).
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
SCRIPT: python x.py dist bootstrap --include-default-paths
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
CODEGEN_BACKENDS: llvm,cranelift
|
||||
|
|
@ -607,9 +601,6 @@ auto:
|
|||
RUST_CONFIGURE_ARGS: >-
|
||||
--build=x86_64-pc-windows-gnu
|
||||
--enable-full-tools
|
||||
# We are intentionally allowing an old toolchain on this builder (and that's
|
||||
# incompatible with LLVM downloads today).
|
||||
NO_DOWNLOAD_CI_LLVM: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
CODEGEN_BACKENDS: llvm,cranelift
|
||||
<<: *job-windows
|
||||
|
|
|
|||
|
|
@ -336,14 +336,14 @@ pub(crate) fn run_global_ctxt(
|
|||
|
||||
// NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
|
||||
let _ = tcx.sess.time("wf_checking", || {
|
||||
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
|
||||
tcx.hir().try_par_for_each_module(|module| tcx.ensure_ok().check_mod_type_wf(module))
|
||||
});
|
||||
|
||||
tcx.dcx().abort_if_errors();
|
||||
|
||||
tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
|
||||
tcx.sess.time("check_mod_attrs", || {
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
|
||||
tcx.hir().for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module))
|
||||
});
|
||||
rustc_passes::stability::check_unused_or_stable_features(tcx);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@ impl<'tcx> LateLintPass<'tcx> for ClippyCtfe {
|
|||
_: Span,
|
||||
defid: LocalDefId,
|
||||
) {
|
||||
cx.tcx.ensure().mir_drops_elaborated_and_const_checked(defid); // Lint
|
||||
cx.tcx.ensure_ok().mir_drops_elaborated_and_const_checked(defid); // Lint
|
||||
}
|
||||
}
|
||||
|
|
|
|||
21
tests/codegen/issues/issue-136329-optnone-noinline.rs
Normal file
21
tests/codegen/issues/issue-136329-optnone-noinline.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//! Ensure that `#[optimize(none)]` functions are never inlined
|
||||
|
||||
//@ compile-flags: -Copt-level=3
|
||||
|
||||
#![feature(optimize_attribute)]
|
||||
|
||||
#[optimize(none)]
|
||||
pub fn foo() {
|
||||
let _x = 123;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}}void @bar
|
||||
// CHECK: start:
|
||||
// CHECK: {{.*}}call {{.*}}void
|
||||
// CHECK: ret void
|
||||
#[no_mangle]
|
||||
pub fn bar() {
|
||||
foo();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -29,7 +29,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/coerce-expect-unsized-ascribed.rs:14:27
|
||||
|
|
||||
LL | let _ = type_ascribe!(Box::new( { |x| (x as u8) }), Box<dyn Fn(i32) -> _>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:14:39}>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@...}>`
|
||||
|
|
||||
= note: expected struct `Box<dyn Fn(i32) -> u8>`
|
||||
found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:14:39: 14:42}>`
|
||||
|
|
@ -85,7 +85,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/coerce-expect-unsized-ascribed.rs:22:27
|
||||
|
|
||||
LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _);
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@coerce-expect-unsized-ascribed.rs:22:30}`
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@...}`
|
||||
|
|
||||
= note: expected reference `&dyn Fn(i32) -> u8`
|
||||
found reference `&{closure@$DIR/coerce-expect-unsized-ascribed.rs:22:30: 22:33}`
|
||||
|
|
@ -123,7 +123,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/coerce-expect-unsized-ascribed.rs:27:27
|
||||
|
|
||||
LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box<dyn Fn(i32) -> _>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:27:36}>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<{closure@...}>`
|
||||
|
|
||||
= note: expected struct `Box<dyn Fn(i32) -> u8>`
|
||||
found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:27:36: 27:39}>`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0271]: type mismatch resolving `<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ...>>, ...>>, ...> as Future>::Error == Foo`
|
||||
error[E0271]: type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||
--> $DIR/E0271.rs:20:5
|
||||
|
|
||||
LL | / Box::new(
|
||||
|
|
@ -7,14 +7,16 @@ LL | | Err::<(), _>(
|
|||
LL | | Ok::<_, ()>(
|
||||
... |
|
||||
LL | | )
|
||||
| |_____^ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
|
||||
| |_____^ type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||
|
|
||||
note: expected this to be `Foo`
|
||||
--> $DIR/E0271.rs:10:18
|
||||
|
|
||||
LL | type Error = E;
|
||||
| ^
|
||||
= note: required for the cast from `Box<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ()>>, ()>>, ()>>` to `Box<(dyn Future<Error = Foo> + 'static)>`
|
||||
= note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.ascii/E0271.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//@ revisions: ascii unicode
|
||||
//@[ascii] compile-flags: --diagnostic-width=40
|
||||
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40
|
||||
//@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
|
||||
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes
|
||||
//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
|
||||
trait Future {
|
||||
type Error;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0271]: type mismatch resolving `<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ...>>, ...>>, ...> as Future>::Error == Foo`
|
||||
error[E0271]: type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||
╭▸ $DIR/E0271.rs:20:5
|
||||
│
|
||||
LL │ ┏ Box::new(
|
||||
|
|
@ -7,14 +7,16 @@ LL │ ┃ Err::<(), _>(
|
|||
LL │ ┃ Ok::<_, ()>(
|
||||
‡ ┃
|
||||
LL │ ┃ )
|
||||
│ ┗━━━━━┛ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
|
||||
│ ┗━━━━━┛ type mismatch resolving `<Result<..., ()> as Future>::Error == Foo`
|
||||
╰╴
|
||||
note: expected this to be `Foo`
|
||||
╭▸ $DIR/E0271.rs:10:18
|
||||
│
|
||||
LL │ type Error = E;
|
||||
│ ━
|
||||
╰ note: required for the cast from `Box<Result<Result<(), Result<Result<(), Result<Result<(), Option<{integer}>>, ()>>, ()>>, ()>>` to `Box<(dyn Future<Error = Foo> + 'static)>`
|
||||
├ note: required for the cast from `Box<Result<..., ()>>` to `Box<...>`
|
||||
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.unicode/E0271.long-type-hash.txt'
|
||||
╰ note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
|
|||
LL | | Ok("")
|
||||
LL | | ))))))))))))))))))))))))))))))
|
||||
LL | | ))))))))))))))))))))))))))))));
|
||||
| |__________________________________^ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
||||
| |__________________________________^ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||
|
|
||||
= note: expected struct `Atype<Btype<..., ...>, ...>`
|
||||
found enum `Result<Result<..., ...>, ...>`
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||
found enum `Result<Result<..., _>, _>`
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
|
@ -32,11 +32,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
|
|||
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||
LL | | ))))))))))))))))))))))))))))))
|
||||
LL | | ))))))))))))))))))))))));
|
||||
| |____________________________^ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
||||
| |____________________________^ expected `Option<Result<Option<Option<...>>, _>>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||
|
|
||||
= note: expected enum `Option<Result<..., ...>>`
|
||||
found enum `Result<Result<..., ...>, ...>`
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: expected enum `Option<Result<Option<...>, _>>`
|
||||
found enum `Result<Result<..., _>, _>`
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
|
@ -50,13 +50,13 @@ LL | | Atype<
|
|||
... |
|
||||
LL | | i32
|
||||
LL | | > = ();
|
||||
| | - ^^ expected `Atype<Btype<..., ...>, ...>`, found `()`
|
||||
| | - ^^ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `()`
|
||||
| |_____|
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `Atype<Btype<..., ...>, ...>`
|
||||
= note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||
found unit type `()`
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
|
@ -70,11 +70,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
|
|||
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||
LL | | ))))))))))))))))))))))))))))))
|
||||
LL | | ))))))))))))))))))))))));
|
||||
| |____________________________^ expected `()`, found `Result<Result<..., ...>, ...>`
|
||||
| |____________________________^ expected `()`, found `Result<Result<Result<..., _>, _>, _>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found enum `Result<Result<..., ...>, ...>`
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
found enum `Result<Result<..., _>, _>`
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O…
|
|||
LL │ ┃ Ok("")
|
||||
LL │ ┃ ))))))))))))))))))))))))))))))
|
||||
LL │ ┃ ))))))))))))))))))))))))))))));
|
||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||
│
|
||||
├ note: expected struct `Atype<Btype<..., ...>, ...>`
|
||||
│ found enum `Result<Result<..., ...>, ...>`
|
||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
├ note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||
│ found enum `Result<Result<..., _>, _>`
|
||||
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
╰ note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
|
@ -32,11 +32,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok…
|
|||
LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||
LL │ ┃ ))))))))))))))))))))))))))))))
|
||||
LL │ ┃ ))))))))))))))))))))))));
|
||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option<Result<Option<Option<...>>, _>>`, found `Result<Result<Result<..., _>, _>, _>`
|
||||
│
|
||||
├ note: expected enum `Option<Result<..., ...>>`
|
||||
│ found enum `Result<Result<..., ...>, ...>`
|
||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
├ note: expected enum `Option<Result<Option<...>, _>>`
|
||||
│ found enum `Result<Result<..., _>, _>`
|
||||
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
╰ note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
|
@ -50,13 +50,13 @@ LL │ │ Atype<
|
|||
‡ │
|
||||
LL │ │ i32
|
||||
LL │ │ > = ();
|
||||
│ │ │ ━━ expected `Atype<Btype<..., ...>, ...>`, found `()`
|
||||
│ │ │ ━━ expected `Atype<Btype<Ctype<..., i32>, i32>, i32>`, found `()`
|
||||
│ └─────┤
|
||||
│ expected due to this
|
||||
│
|
||||
├ note: expected struct `Atype<Btype<..., ...>, ...>`
|
||||
├ note: expected struct `Atype<Btype<..., i32>, i32>`
|
||||
│ found unit type `()`
|
||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
╰ note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
|
@ -70,11 +70,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok…
|
|||
LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
|
||||
LL │ ┃ ))))))))))))))))))))))))))))))
|
||||
LL │ ┃ ))))))))))))))))))))))));
|
||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result<Result<..., ...>, ...>`
|
||||
│ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result<Result<Result<..., _>, _>, _>`
|
||||
│
|
||||
├ note: expected unit type `()`
|
||||
│ found enum `Result<Result<..., ...>, ...>`
|
||||
├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
│ found enum `Result<Result<..., _>, _>`
|
||||
├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
╰ note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
|
|
|||
15
tests/ui/diagnostic-width/long-e0277.rs
Normal file
15
tests/ui/diagnostic-width/long-e0277.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
|
||||
// The regex below normalizes the long type file name to make it suitable for compare-modes.
|
||||
//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
|
||||
type A = (i32, i32, i32, i32);
|
||||
type B = (A, A, A, A);
|
||||
type C = (B, B, B, B);
|
||||
type D = (C, C, C, C);
|
||||
|
||||
trait Trait {}
|
||||
|
||||
fn require_trait<T: Trait>() {}
|
||||
|
||||
fn main() {
|
||||
require_trait::<D>(); //~ ERROR the trait bound `(...
|
||||
}
|
||||
23
tests/ui/diagnostic-width/long-e0277.stderr
Normal file
23
tests/ui/diagnostic-width/long-e0277.stderr
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
error[E0277]: the trait bound `(..., ..., ..., ...): Trait` is not satisfied
|
||||
--> $DIR/long-e0277.rs:14:21
|
||||
|
|
||||
LL | require_trait::<D>();
|
||||
| ^ unsatisfied trait bound
|
||||
|
|
||||
= help: the trait `Trait` is not implemented for `(..., ..., ..., ...)`
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/long-e0277.rs:9:1
|
||||
|
|
||||
LL | trait Trait {}
|
||||
| ^^^^^^^^^^^
|
||||
note: required by a bound in `require_trait`
|
||||
--> $DIR/long-e0277.rs:11:21
|
||||
|
|
||||
LL | fn require_trait<T: Trait>() {}
|
||||
| ^^^^^ required by this bound in `require_trait`
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
@ -2,13 +2,13 @@ error[E0382]: use of moved value: `x`
|
|||
--> $DIR/non-copy-type-moved.rs:16:14
|
||||
|
|
||||
LL | fn foo(x: D) {
|
||||
| - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait
|
||||
| - move occurs because `x` has type `(..., ..., ..., ...)`, which does not implement the `Copy` trait
|
||||
LL | let _a = x;
|
||||
| - value moved here
|
||||
LL | let _b = x;
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ fn foo(x: D) {
|
|||
//~^ NOTE this expression has type `((...,
|
||||
//~| NOTE expected `((...,
|
||||
//~| NOTE expected tuple
|
||||
//~| NOTE the full type name has been written to
|
||||
//~| NOTE the full name for the type has been written to
|
||||
//~| NOTE consider using `--verbose` to print the full type name to the console
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ LL | let () = x;
|
|||
|
|
||||
= note: expected tuple `((..., ..., ..., ...), ..., ..., ...)`
|
||||
found unit type `()`
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ LL | let d: &fn(u32) -> u32 = foo;
|
|||
help: consider using a reference
|
||||
|
|
||||
LL | let d: &fn(u32) -> u32 = &foo;
|
||||
| ~~~~
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-pointer-mismatch.rs:48:30
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ LL | let _: fn(isize) -> usize = callee;
|
|||
help: consider casting to a fn pointer
|
||||
|
|
||||
LL | let _: fn(isize) -> usize = callee as fn(isize) -> usize;
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| +++++++++++++++++++++
|
||||
|
||||
error[E0605]: non-primitive cast: `fn(isize) -> usize {callee}` as `fn(isize) -> usize`
|
||||
--> $DIR/cast.rs:15:13
|
||||
|
|
@ -32,7 +32,7 @@ LL | callee,
|
|||
help: consider casting to a fn pointer
|
||||
|
|
||||
LL | callee as fn(isize) -> usize,
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| +++++++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ LL | | ),
|
|||
LL | | ) {
|
||||
| |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
|
||||
LL | f
|
||||
| ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)`
|
||||
| ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...))))`, found `&dyn Fn(u32)`
|
||||
|
|
||||
= note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))`
|
||||
found reference `&dyn Fn(u32)`
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/box-future-wrong-output.rs:20:39
|
||||
|
|
||||
LL | let _: BoxFuture<'static, bool> = async {}.boxed();
|
||||
| ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
||||
| ------------------------ ^^^^^^^^^^^^^^^^ expected `Pin<Box<...>>`, found `Pin<Box<dyn Future<Output = ()> + Send>>`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ error[E0308]: mismatched types
|
|||
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
| - found this type parameter
|
||||
LL | Pin::new(x)
|
||||
| -------- ^ expected `Box<dyn Future<Output = ...> + Send>`, found type parameter `F`
|
||||
| -------- ^ expected `Box<dyn Future<Output = i32> + Send>`, found type parameter `F`
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
| help: use `Box::pin` to pin and box this expression: `Box::pin`
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-107860.rs:3:36
|
||||
|
|
||||
LL | async fn str<T>(T: &str) -> &str { &str }
|
||||
| ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<...>}`
|
||||
| ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<_>}`
|
||||
|
|
||||
= note: expected reference `&str`
|
||||
found reference `&for<'a> fn(&'a str) -> impl Future<Output = &'a str> {str::<_>}`
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<dyn Pointee<Metadata = ()> as Pointee>::
|
|||
--> $DIR/ice-with-dyn-pointee-errors.rs:9:33
|
||||
|
|
||||
LL | unknown_sized_object_ptr_in(x)
|
||||
| --------------------------- ^ expected `()`, found `DynMetadata<dyn Pointee<Metadata = ...>>`
|
||||
| --------------------------- ^ expected `()`, found `DynMetadata<dyn Pointee<Metadata = ()>>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/pretty.rs:36:79
|
||||
|
|
||||
LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x }
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>`
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = &u8>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>`
|
||||
|
|
||||
|
|
@ -132,7 +132,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/pretty.rs:38:73
|
||||
|
|
||||
LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x }
|
||||
| - ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = ...>`
|
||||
| - ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = u8>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn AnyDifferentBinders<Assoc = u8>`
|
||||
|
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ LL | | ))))))))))),
|
|||
LL | | )))))))))))
|
||||
| |_______________- return type was inferred to be `Option<Option<Option<...>>>` here
|
||||
|
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
= help: the trait `std::fmt::Display` is not implemented for `Option<Option<Option<...>>>`
|
||||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
= note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ LL | map.insert(1, Struct::do_something);
|
|||
| |
|
||||
| ... which causes `map` to have type `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
|
||||
LL | Self { map }
|
||||
| ^^^ expected `HashMap<u16, fn(u8) -> Pin<...>>`, found `HashMap<{integer}, ...>`
|
||||
| ^^^ expected `HashMap<u16, fn(u8) -> Pin<Box<...>>>`, found `HashMap<{integer}, ...>`
|
||||
|
|
||||
= note: expected struct `HashMap<u16, fn(_) -> Pin<Box<(dyn Future<Output = ()> + Send + 'static)>>>`
|
||||
found struct `HashMap<{integer}, fn(_) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
fn foo() { //~ HELP try adding a return type
|
||||
vec!['a'].iter().map(|c| c)
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| NOTE expected `()`, found `Map<Iter<'_, char>, ...>`
|
||||
//~| NOTE expected `()`, found `Map<Iter<'_, char>, {closure@...}>`
|
||||
//~| NOTE expected unit type `()`
|
||||
//~| HELP consider using a semicolon here
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/return_type_containing_closure.rs:3:5
|
||||
|
|
||||
LL | vec!['a'].iter().map(|c| c)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map<Iter<'_, char>, ...>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map<Iter<'_, char>, {closure@...}>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found struct `Map<std::slice::Iter<'_, char>, {closure@$DIR/return_type_containing_closure.rs:3:26: 3:29}>`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue