Rollup merge of #126620 - oli-obk:taint_errors, r=fee1-dead
Actually taint InferCtxt when a fulfillment error is emitted And avoid checking the global error counter fixes #122044 fixes #123255 fixes #123276 fixes #125799
This commit is contained in:
commit
e7be3562b7
42 changed files with 595 additions and 238 deletions
|
@ -2776,97 +2776,115 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
let mut this = "this bound";
|
||||
let mut note = None;
|
||||
let mut help = None;
|
||||
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
|
||||
&& let ty::ClauseKind::Trait(trait_pred) = clause
|
||||
{
|
||||
let def_id = trait_pred.def_id();
|
||||
let visible_item = if let Some(local) = def_id.as_local() {
|
||||
// Check for local traits being reachable.
|
||||
let vis = &tcx.resolutions(()).effective_visibilities;
|
||||
// Account for non-`pub` traits in the root of the local crate.
|
||||
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
|
||||
vis.is_reachable(local) || is_locally_reachable
|
||||
} else {
|
||||
// Check for foreign traits being reachable.
|
||||
tcx.visible_parent_map(()).get(&def_id).is_some()
|
||||
};
|
||||
if tcx.is_lang_item(def_id, LangItem::Sized) {
|
||||
// Check if this is an implicit bound, even in foreign crates.
|
||||
if tcx
|
||||
.generics_of(item_def_id)
|
||||
.own_params
|
||||
.iter()
|
||||
.any(|param| tcx.def_span(param.def_id) == span)
|
||||
{
|
||||
a = "an implicit `Sized`";
|
||||
this = "the implicit `Sized` requirement on this type parameter";
|
||||
}
|
||||
if let Some(hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Type(bounds, None),
|
||||
..
|
||||
})) = tcx.hir().get_if_local(item_def_id)
|
||||
// Do not suggest relaxing if there is an explicit `Sized` obligation.
|
||||
&& !bounds.iter()
|
||||
.filter_map(|bound| bound.trait_ref())
|
||||
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
|
||||
{
|
||||
let (span, separator) = if let [.., last] = bounds {
|
||||
(last.span().shrink_to_hi(), " +")
|
||||
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() {
|
||||
match clause {
|
||||
ty::ClauseKind::Trait(trait_pred) => {
|
||||
let def_id = trait_pred.def_id();
|
||||
let visible_item = if let Some(local) = def_id.as_local() {
|
||||
// Check for local traits being reachable.
|
||||
let vis = &tcx.resolutions(()).effective_visibilities;
|
||||
// Account for non-`pub` traits in the root of the local crate.
|
||||
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
|
||||
vis.is_reachable(local) || is_locally_reachable
|
||||
} else {
|
||||
(generics.span.shrink_to_hi(), ":")
|
||||
// Check for foreign traits being reachable.
|
||||
tcx.visible_parent_map(()).get(&def_id).is_some()
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"consider relaxing the implicit `Sized` restriction",
|
||||
format!("{separator} ?Sized"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if tcx.is_lang_item(def_id, LangItem::Sized) {
|
||||
// Check if this is an implicit bound, even in foreign crates.
|
||||
if tcx
|
||||
.generics_of(item_def_id)
|
||||
.own_params
|
||||
.iter()
|
||||
.any(|param| tcx.def_span(param.def_id) == span)
|
||||
{
|
||||
a = "an implicit `Sized`";
|
||||
this =
|
||||
"the implicit `Sized` requirement on this type parameter";
|
||||
}
|
||||
if let Some(hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Type(bounds, None),
|
||||
..
|
||||
})) = tcx.hir().get_if_local(item_def_id)
|
||||
// Do not suggest relaxing if there is an explicit `Sized` obligation.
|
||||
&& !bounds.iter()
|
||||
.filter_map(|bound| bound.trait_ref())
|
||||
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
|
||||
{
|
||||
let (span, separator) = if let [.., last] = bounds {
|
||||
(last.span().shrink_to_hi(), " +")
|
||||
} else {
|
||||
(generics.span.shrink_to_hi(), ":")
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"consider relaxing the implicit `Sized` restriction",
|
||||
format!("{separator} ?Sized"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let DefKind::Trait = tcx.def_kind(item_def_id)
|
||||
&& !visible_item
|
||||
{
|
||||
note = Some(format!(
|
||||
"`{short_item_name}` is a \"sealed trait\", because to implement it \
|
||||
you also need to implement `{}`, which is not accessible; this is \
|
||||
usually done to force you to use one of the provided types that \
|
||||
already implement it",
|
||||
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
|
||||
));
|
||||
let impls_of = tcx.trait_impls_of(def_id);
|
||||
let impls = impls_of
|
||||
.non_blanket_impls()
|
||||
.values()
|
||||
.flatten()
|
||||
.chain(impls_of.blanket_impls().iter())
|
||||
.collect::<Vec<_>>();
|
||||
if !impls.is_empty() {
|
||||
let len = impls.len();
|
||||
let mut types = impls
|
||||
.iter()
|
||||
.map(|t| {
|
||||
with_no_trimmed_paths!(format!(
|
||||
" {}",
|
||||
tcx.type_of(*t).instantiate_identity(),
|
||||
))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let post = if types.len() > 9 {
|
||||
types.truncate(8);
|
||||
format!("\nand {} others", len - 8)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
help = Some(format!(
|
||||
"the following type{} implement{} the trait:\n{}{post}",
|
||||
pluralize!(len),
|
||||
if len == 1 { "s" } else { "" },
|
||||
types.join("\n"),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let DefKind::Trait = tcx.def_kind(item_def_id)
|
||||
&& !visible_item
|
||||
{
|
||||
note = Some(format!(
|
||||
"`{short_item_name}` is a \"sealed trait\", because to implement it \
|
||||
you also need to implement `{}`, which is not accessible; this is \
|
||||
usually done to force you to use one of the provided types that \
|
||||
already implement it",
|
||||
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
|
||||
));
|
||||
let impls_of = tcx.trait_impls_of(def_id);
|
||||
let impls = impls_of
|
||||
.non_blanket_impls()
|
||||
.values()
|
||||
.flatten()
|
||||
.chain(impls_of.blanket_impls().iter())
|
||||
.collect::<Vec<_>>();
|
||||
if !impls.is_empty() {
|
||||
let len = impls.len();
|
||||
let mut types = impls
|
||||
.iter()
|
||||
.map(|t| {
|
||||
with_no_trimmed_paths!(format!(
|
||||
" {}",
|
||||
tcx.type_of(*t).instantiate_identity(),
|
||||
))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let post = if types.len() > 9 {
|
||||
types.truncate(8);
|
||||
format!("\nand {} others", len - 8)
|
||||
ty::ClauseKind::ConstArgHasType(..) => {
|
||||
let descr =
|
||||
format!("required by a const generic parameter in `{item_name}`");
|
||||
if span.is_visible(sm) {
|
||||
let msg = format!(
|
||||
"required by this const generic parameter in `{short_item_name}`"
|
||||
);
|
||||
multispan.push_span_label(span, msg);
|
||||
err.span_note(multispan, descr);
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
help = Some(format!(
|
||||
"the following type{} implement{} the trait:\n{}{post}",
|
||||
pluralize!(len),
|
||||
if len == 1 { "s" } else { "" },
|
||||
types.join("\n"),
|
||||
));
|
||||
err.span_note(tcx.def_span(item_def_id), descr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
}
|
||||
let descr = format!("required by {a} bound in `{item_name}`");
|
||||
if span.is_visible(sm) {
|
||||
let msg = format!("required by {this} in `{short_item_name}`");
|
||||
|
|
|
@ -179,6 +179,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
|
||||
if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
|
||||
let guar = self.report_fulfillment_error(error);
|
||||
self.infcx.set_tainted_by_errors(guar);
|
||||
reported = Some(guar);
|
||||
// We want to ignore desugarings here: spans are equivalent even
|
||||
// if one is the result of a desugaring and the other is not.
|
||||
|
@ -2686,22 +2687,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Given some `ConstArgHasType(?x, usize)`, we should not emit an error such as
|
||||
// "type annotations needed: cannot satisfy the constant `_` has type `usize`"
|
||||
// Instead we should emit a normal error suggesting the user to turbofish the
|
||||
// const parameter that is currently being inferred. Unfortunately we cannot
|
||||
// nicely emit such an error so we delay an ICE incase nobody else reports it
|
||||
// for us.
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||
return self.tcx.sess.dcx().span_delayed_bug(
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
|
||||
.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
format!(
|
||||
"`ambiguous ConstArgHasType({:?}, {:?}) unaccompanied by inference error`",
|
||||
ct, ty
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ct.into(),
|
||||
ErrorCode::E0284,
|
||||
true,
|
||||
),
|
||||
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
|
||||
if term.is_infer() =>
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue