Rollup merge of #120342 - oli-obk:track_errors6, r=nnethercote
Remove various `has_errors` or `err_count` uses follow up to https://github.com/rust-lang/rust/pull/119895 r? `@nnethercote` since you recently did something similar. There are so many more of these, but I wanted to get a PR out instead of growing the commit list indefinitely. The commits all work on their own and can be reviewed commit by commit.
This commit is contained in:
commit
b28e6f143e
9 changed files with 186 additions and 193 deletions
|
@ -99,7 +99,7 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||
obligation: PredicateObligation<'tcx>,
|
||||
root_obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>,
|
||||
);
|
||||
) -> ErrorGuaranteed;
|
||||
|
||||
fn emit_specialized_closure_kind_error(
|
||||
&self,
|
||||
|
@ -107,7 +107,10 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Option<ErrorGuaranteed>;
|
||||
|
||||
fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool;
|
||||
fn fn_arg_obligation(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed>;
|
||||
|
||||
fn try_conversion_context(
|
||||
&self,
|
||||
|
@ -142,6 +145,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
(
|
||||
span,
|
||||
predicates
|
||||
.0
|
||||
.iter()
|
||||
.map(|&predicate| ErrorDescriptor { predicate, index: None })
|
||||
.collect(),
|
||||
|
@ -208,10 +212,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut reported = None;
|
||||
|
||||
for from_expansion in [false, true] {
|
||||
for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
|
||||
if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
|
||||
self.report_fulfillment_error(error);
|
||||
let guar = self.report_fulfillment_error(error);
|
||||
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.
|
||||
let mut span = error.obligation.cause.span;
|
||||
|
@ -222,13 +229,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
self.reported_trait_errors
|
||||
.borrow_mut()
|
||||
.entry(span)
|
||||
.or_default()
|
||||
.or_insert_with(|| (vec![], guar))
|
||||
.0
|
||||
.push(error.obligation.predicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.dcx().delayed_bug("expected fulfillment errors")
|
||||
// It could be that we don't report an error because we have seen an `ErrorReported` from another source.
|
||||
// We should probably be able to fix most of these, but some are delayed bugs that get a proper error
|
||||
// after this function.
|
||||
reported.unwrap_or_else(|| self.dcx().delayed_bug("failed to report fulfillment errors"))
|
||||
}
|
||||
|
||||
/// Reports that an overflow has occurred and halts compilation. We
|
||||
|
@ -374,7 +385,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
mut obligation: PredicateObligation<'tcx>,
|
||||
root_obligation: &PredicateObligation<'tcx>,
|
||||
error: &SelectionError<'tcx>,
|
||||
) {
|
||||
) -> ErrorGuaranteed {
|
||||
let tcx = self.tcx;
|
||||
|
||||
if tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default()
|
||||
|
@ -384,10 +395,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
let mut span = obligation.cause.span;
|
||||
// FIXME: statically guarantee this by tainting after the diagnostic is emitted
|
||||
self.set_tainted_by_errors(
|
||||
tcx.dcx().span_delayed_bug(span, "`report_selection_error` did not emit an error"),
|
||||
);
|
||||
|
||||
let mut err = match *error {
|
||||
SelectionError::Unimplemented => {
|
||||
|
@ -412,21 +419,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
kind: _,
|
||||
} = *obligation.cause.code()
|
||||
{
|
||||
self.report_extra_impl_obligation(
|
||||
return self.report_extra_impl_obligation(
|
||||
span,
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
&format!("`{}`", obligation.predicate),
|
||||
)
|
||||
.emit();
|
||||
return;
|
||||
.emit()
|
||||
}
|
||||
|
||||
// Report a const-param specific error
|
||||
if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives()
|
||||
{
|
||||
self.report_const_param_not_wf(ty, &obligation).emit();
|
||||
return;
|
||||
return self.report_const_param_not_wf(ty, &obligation).emit();
|
||||
}
|
||||
|
||||
let bound_predicate = obligation.predicate.kind();
|
||||
|
@ -436,22 +441,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
|
||||
if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
|
||||
return;
|
||||
if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
|
||||
return guar;
|
||||
}
|
||||
|
||||
// FIXME(effects)
|
||||
let predicate_is_const = false;
|
||||
|
||||
if self.dcx().has_errors().is_some()
|
||||
if let Some(guar) = self.dcx().has_errors()
|
||||
&& trait_predicate.references_error()
|
||||
{
|
||||
return;
|
||||
return guar;
|
||||
}
|
||||
if self.fn_arg_obligation(&obligation) {
|
||||
// Silence redundant errors on binding acccess that are already
|
||||
// reported on the binding definition (#56607).
|
||||
return;
|
||||
// Silence redundant errors on binding acccess that are already
|
||||
// reported on the binding definition (#56607).
|
||||
if let Err(guar) = self.fn_arg_obligation(&obligation) {
|
||||
return guar;
|
||||
}
|
||||
let mut file = None;
|
||||
let (post_message, pre_message, type_def) = self
|
||||
|
@ -515,7 +520,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
trait_ref,
|
||||
span,
|
||||
) {
|
||||
GetSafeTransmuteErrorAndReason::Silent => return,
|
||||
GetSafeTransmuteErrorAndReason::Silent => return self.dcx().span_delayed_bug(span, "silent safe transmute error"),
|
||||
GetSafeTransmuteErrorAndReason::Error {
|
||||
err_msg,
|
||||
safe_transmute_explanation,
|
||||
|
@ -576,8 +581,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
have_alt_message,
|
||||
) {
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
err.emit();
|
||||
return;
|
||||
return err.emit();
|
||||
}
|
||||
|
||||
file_note.map(|note| err.note(note));
|
||||
|
@ -680,13 +684,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) {
|
||||
err.emit();
|
||||
return;
|
||||
return err.emit();
|
||||
}
|
||||
|
||||
if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
|
||||
err.emit();
|
||||
return;
|
||||
return err.emit();
|
||||
}
|
||||
|
||||
if is_unsize {
|
||||
|
@ -776,8 +778,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
Some(sym::Debug | sym::Display)
|
||||
)
|
||||
{
|
||||
err.emit();
|
||||
return;
|
||||
return err.emit();
|
||||
}
|
||||
|
||||
err
|
||||
|
@ -912,8 +913,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
found_trait_ref,
|
||||
expected_trait_ref,
|
||||
) {
|
||||
Some(err) => err,
|
||||
None => return,
|
||||
Ok(err) => err,
|
||||
Err(guar) => return guar,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -934,15 +935,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
|
||||
match self.report_not_const_evaluatable_error(&obligation, span) {
|
||||
Some(err) => err,
|
||||
None => return,
|
||||
Ok(err) => err,
|
||||
Err(guar) => return guar,
|
||||
}
|
||||
}
|
||||
|
||||
// Already reported in the query.
|
||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) |
|
||||
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) |
|
||||
// Already reported.
|
||||
Overflow(OverflowError::Error(_)) => return,
|
||||
Overflow(OverflowError::Error(guar)) => return guar,
|
||||
|
||||
Overflow(_) => {
|
||||
bug!("overflow should be handled before the `report_selection_error` path");
|
||||
|
@ -951,7 +952,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
self.note_obligation_cause(&mut err, &obligation);
|
||||
self.point_at_returns_when_relevant(&mut err, &obligation);
|
||||
err.emit();
|
||||
err.emit()
|
||||
}
|
||||
|
||||
fn emit_specialized_closure_kind_error(
|
||||
|
@ -986,7 +987,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool {
|
||||
fn fn_arg_obligation(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
|
||||
obligation.cause.code()
|
||||
&& let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id)
|
||||
|
@ -996,12 +1000,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
hir::Path { res: hir::def::Res::Local(hir_id), .. },
|
||||
)) = arg.kind
|
||||
&& let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id)
|
||||
&& let Some(preds) = self.reported_trait_errors.borrow().get(&pat.span)
|
||||
&& let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span)
|
||||
&& preds.contains(&obligation.predicate)
|
||||
{
|
||||
return true;
|
||||
return Err(*guar);
|
||||
}
|
||||
false
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// When the `E` of the resulting `Result<T, E>` in an expression `foo().bar().baz()?`,
|
||||
|
@ -1323,13 +1327,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
|
|||
// `error` occurring implies that `cond` occurs.
|
||||
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
|
||||
|
||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>);
|
||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed;
|
||||
|
||||
fn report_projection_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &MismatchedProjectionTypes<'tcx>,
|
||||
);
|
||||
) -> ErrorGuaranteed;
|
||||
|
||||
fn maybe_detailed_projection_msg(
|
||||
&self,
|
||||
|
@ -1395,7 +1399,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
|
|||
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
|
||||
) -> PredicateObligation<'tcx>;
|
||||
|
||||
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>);
|
||||
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed;
|
||||
|
||||
fn predicate_can_apply(
|
||||
&self,
|
||||
|
@ -1512,13 +1516,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
|
|||
span: Span,
|
||||
found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx>>;
|
||||
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>;
|
||||
|
||||
fn report_not_const_evaluatable_error(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<DiagnosticBuilder<'tcx>>;
|
||||
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>;
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
|
@ -1564,7 +1568,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
|
||||
fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
|
||||
if self.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default()
|
||||
== DumpSolverProofTree::OnError
|
||||
{
|
||||
|
@ -1572,31 +1576,29 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
match error.code {
|
||||
FulfillmentErrorCode::SelectionError(ref selection_error) => {
|
||||
self.report_selection_error(
|
||||
FulfillmentErrorCode::SelectionError(ref selection_error) => self
|
||||
.report_selection_error(
|
||||
error.obligation.clone(),
|
||||
&error.root_obligation,
|
||||
selection_error,
|
||||
);
|
||||
}
|
||||
),
|
||||
FulfillmentErrorCode::ProjectionError(ref e) => {
|
||||
self.report_projection_error(&error.obligation, e);
|
||||
self.report_projection_error(&error.obligation, e)
|
||||
}
|
||||
FulfillmentErrorCode::Ambiguity { overflow: false } => {
|
||||
self.maybe_report_ambiguity(&error.obligation);
|
||||
self.maybe_report_ambiguity(&error.obligation)
|
||||
}
|
||||
FulfillmentErrorCode::Ambiguity { overflow: true } => {
|
||||
self.report_overflow_no_abort(error.obligation.clone());
|
||||
self.report_overflow_no_abort(error.obligation.clone())
|
||||
}
|
||||
FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => {
|
||||
self.report_mismatched_types(
|
||||
FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => self
|
||||
.report_mismatched_types(
|
||||
&error.obligation.cause,
|
||||
expected_found.expected,
|
||||
expected_found.found,
|
||||
*err,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
.emit(),
|
||||
FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => {
|
||||
let mut diag = self.report_mismatched_consts(
|
||||
&error.obligation.cause,
|
||||
|
@ -1620,11 +1622,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
&mut Default::default(),
|
||||
);
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
FulfillmentErrorCode::Cycle(ref cycle) => {
|
||||
self.report_overflow_obligation_cycle(cycle);
|
||||
diag.emit()
|
||||
}
|
||||
FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1633,11 +1633,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &MismatchedProjectionTypes<'tcx>,
|
||||
) {
|
||||
) -> ErrorGuaranteed {
|
||||
let predicate = self.resolve_vars_if_possible(obligation.predicate);
|
||||
|
||||
if predicate.references_error() {
|
||||
return;
|
||||
if let Err(e) = predicate.error_reported() {
|
||||
return e;
|
||||
}
|
||||
|
||||
self.probe(|_| {
|
||||
|
@ -1802,8 +1802,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
false,
|
||||
);
|
||||
self.note_obligation_cause(&mut diag, obligation);
|
||||
diag.emit();
|
||||
});
|
||||
diag.emit()
|
||||
})
|
||||
}
|
||||
|
||||
fn maybe_detailed_projection_msg(
|
||||
|
@ -2341,7 +2341,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
|
||||
fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed {
|
||||
// Unable to successfully determine, probably means
|
||||
// insufficient type information, but could mean
|
||||
// ambiguous impls. The latter *ought* to be a
|
||||
|
@ -2361,8 +2361,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let trait_ref = bound_predicate.rebind(data.trait_ref);
|
||||
debug!(?trait_ref);
|
||||
|
||||
if predicate.references_error() {
|
||||
return;
|
||||
if let Err(e) = predicate.error_reported() {
|
||||
return e;
|
||||
}
|
||||
|
||||
// This is kind of a hack: it frequently happens that some earlier
|
||||
|
@ -2381,17 +2381,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// check upstream for type errors and don't add the obligations to
|
||||
// begin with in those cases.
|
||||
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
|
||||
if let None = self.tainted_by_errors() {
|
||||
let err = self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
trait_ref.self_ty().skip_binder().into(),
|
||||
ErrorCode::E0282,
|
||||
false,
|
||||
);
|
||||
err.stash(span, StashKey::MaybeForgetReturn);
|
||||
match self.tainted_by_errors() {
|
||||
None => {
|
||||
let err = self.emit_inference_failure_err(
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
trait_ref.self_ty().skip_binder().into(),
|
||||
ErrorCode::E0282,
|
||||
false,
|
||||
);
|
||||
err.stash(span, StashKey::MaybeForgetReturn);
|
||||
return self.dcx().delayed_bug("stashed error never reported");
|
||||
}
|
||||
Some(e) => return e,
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Typically, this ambiguity should only happen if
|
||||
|
@ -2450,19 +2453,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
|
||||
if self.tainted_by_errors().is_some() && subst.is_none() {
|
||||
if let Some(e) = self.tainted_by_errors()
|
||||
&& subst.is_none()
|
||||
{
|
||||
// If `subst.is_none()`, then this is probably two param-env
|
||||
// candidates or impl candidates that are equal modulo lifetimes.
|
||||
// Therefore, if we've already emitted an error, just skip this
|
||||
// one, since it's not particularly actionable.
|
||||
err.cancel();
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
|
||||
} else {
|
||||
if self.tainted_by_errors().is_some() {
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
err.cancel();
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
err.note(format!("cannot satisfy `{predicate}`"));
|
||||
let impl_candidates = self
|
||||
|
@ -2613,11 +2618,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
||||
// Same hacky approach as above to avoid deluging user
|
||||
// with error messages.
|
||||
if arg.references_error()
|
||||
|| self.dcx().has_errors().is_some()
|
||||
|| self.tainted_by_errors().is_some()
|
||||
{
|
||||
return;
|
||||
|
||||
if let Err(e) = arg.error_reported() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.dcx().has_errors() {
|
||||
return e;
|
||||
}
|
||||
|
||||
self.emit_inference_failure_err(
|
||||
|
@ -2630,12 +2639,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
ty::PredicateKind::Subtype(data) => {
|
||||
if data.references_error()
|
||||
|| self.dcx().has_errors().is_some()
|
||||
|| self.tainted_by_errors().is_some()
|
||||
{
|
||||
if let Err(e) = data.error_reported() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.dcx().has_errors() {
|
||||
// no need to overload user in such cases
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
let SubtypePredicate { a_is_expected: _, a, b } = data;
|
||||
// both must be type variables, or the other would've been instantiated
|
||||
|
@ -2649,8 +2661,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
|
||||
if predicate.references_error() || self.tainted_by_errors().is_some() {
|
||||
return;
|
||||
if let Err(e) = predicate.error_reported() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
let subst = data
|
||||
.projection_ty
|
||||
|
@ -2681,8 +2696,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
|
||||
if predicate.references_error() || self.tainted_by_errors().is_some() {
|
||||
return;
|
||||
if let Err(e) = predicate.error_reported() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
let subst = data.walk().find(|g| g.is_non_region_infer());
|
||||
if let Some(subst) = subst {
|
||||
|
@ -2707,8 +2725,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
if self.dcx().has_errors().is_some() || self.tainted_by_errors().is_some() {
|
||||
return;
|
||||
if let Some(e) = self.tainted_by_errors() {
|
||||
return e;
|
||||
}
|
||||
if let Some(e) = self.dcx().has_errors() {
|
||||
// no need to overload user in such cases
|
||||
return e;
|
||||
}
|
||||
struct_span_code_err!(
|
||||
self.dcx(),
|
||||
|
@ -2721,7 +2743,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
};
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
err.emit()
|
||||
}
|
||||
|
||||
fn annotate_source_of_ambiguity(
|
||||
|
@ -3441,16 +3463,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
span: Span,
|
||||
found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
|
||||
let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref);
|
||||
let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref);
|
||||
|
||||
if expected_trait_ref.self_ty().references_error() {
|
||||
return None;
|
||||
}
|
||||
expected_trait_ref.self_ty().error_reported()?;
|
||||
|
||||
let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else {
|
||||
return None;
|
||||
return Err(self.dcx().delayed_bug("bound vars outside binder"));
|
||||
};
|
||||
|
||||
let found_did = match *found_trait_ty.kind() {
|
||||
|
@ -3464,7 +3484,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) {
|
||||
// We check closures twice, with obligations flowing in different directions,
|
||||
// but we want to complain about them only once.
|
||||
return None;
|
||||
return Err(self.dcx().span_delayed_bug(span, "already_reported"));
|
||||
}
|
||||
|
||||
let mut not_tupled = false;
|
||||
|
@ -3493,7 +3513,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// This shouldn't be common unless manually implementing one of the
|
||||
// traits manually, but don't make it more confusing when it does
|
||||
// happen.
|
||||
Some(
|
||||
Ok(
|
||||
if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().coroutine_trait()
|
||||
&& not_tupled
|
||||
{
|
||||
|
@ -3542,9 +3562,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
|
||||
if !self.tcx.features().generic_const_exprs {
|
||||
self.dcx()
|
||||
let guar = self
|
||||
.dcx()
|
||||
.struct_span_err(span, "constant expression depends on a generic parameter")
|
||||
// FIXME(const_generics): we should suggest to the user how they can resolve this
|
||||
// issue. However, this is currently not actually possible
|
||||
|
@ -3554,7 +3575,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// be reachable.
|
||||
.with_note("this may fail depending on what value the parameter takes")
|
||||
.emit();
|
||||
return None;
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
match obligation.predicate.kind().skip_binder() {
|
||||
|
@ -3569,13 +3590,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
)),
|
||||
_ => err.help("consider adding a `where` bound using this expression"),
|
||||
};
|
||||
Some(err)
|
||||
Ok(err)
|
||||
}
|
||||
ty::ConstKind::Expr(_) => {
|
||||
let err = self
|
||||
.dcx()
|
||||
.struct_span_err(span, format!("unconstrained generic constant `{ct}`"));
|
||||
Some(err)
|
||||
Ok(err)
|
||||
}
|
||||
_ => {
|
||||
bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue