mod ambiguity;
+pub mod method_chain;
pub mod on_unimplemented;
pub mod suggestions;
};
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt, TyCtxtInferExt};
+use crate::infer::{self, InferCtxt};
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::normalize::QueryNormalizeExt as _;
use crate::traits::specialize::to_pretty_impl_header;
}
pub trait TypeErrCtxtExt<'tcx> {
+ fn report_overflow_error<T>(
+ &self,
+ predicate: &T,
+ span: Span,
+ suggest_increasing_limit: bool,
+ mutate: impl FnOnce(&mut Diagnostic),
+ ) -> !
+ where
+ T: fmt::Display
+ + TypeFoldable<'tcx>
+ + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+ <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
fn report_fulfillment_errors(
&self,
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
) -> ErrorGuaranteed;
- fn report_overflow_error<T>(
+ fn report_overflow_obligation<T>(
&self,
obligation: &Obligation<'tcx, T>,
suggest_increasing_limit: bool,
) -> !
where
- T: fmt::Display
- + TypeFoldable<'tcx>
- + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
- <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+ T: ToPredicate<'tcx> + Clone;
fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
- fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
+ fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
/// The `root_obligation` parameter should be the `root_obligation` field
/// from a `FulfillmentError`. If no `FulfillmentError` is available,
/// occurrences in any case.
fn report_overflow_error<T>(
&self,
- obligation: &Obligation<'tcx, T>,
+ predicate: &T,
+ span: Span,
suggest_increasing_limit: bool,
+ mutate: impl FnOnce(&mut Diagnostic),
) -> !
where
T: fmt::Display
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
{
- let predicate = self.resolve_vars_if_possible(obligation.predicate.clone());
+ let predicate = self.resolve_vars_if_possible(predicate.clone());
let mut pred_str = predicate.to_string();
+
if pred_str.len() > 50 {
// We don't need to save the type to a file, we will be talking about this type already
// in a separate note when we explain the obligation, so it will be available that way.
}
let mut err = struct_span_err!(
self.tcx.sess,
- obligation.cause.span,
+ span,
E0275,
"overflow evaluating the requirement `{}`",
pred_str,
self.suggest_new_overflow_limit(&mut err);
}
- self.note_obligation_cause_code(
- &mut err,
- &obligation.predicate,
- obligation.param_env,
- obligation.cause.code(),
- &mut vec![],
- &mut Default::default(),
- );
+ mutate(&mut err);
err.emit();
self.tcx.sess.abort_if_errors();
bug!();
}
+ /// Reports that an overflow has occurred and halts compilation. We
+ /// halt compilation unconditionally because it is important that
+ /// overflows never be masked -- they basically represent computations
+ /// whose result could not be truly determined and thus we can't say
+ /// if the program type checks or not -- and they are unusual
+ /// occurrences in any case.
+ fn report_overflow_obligation<T>(
+ &self,
+ obligation: &Obligation<'tcx, T>,
+ suggest_increasing_limit: bool,
+ ) -> !
+ where
+ T: ToPredicate<'tcx> + Clone,
+ {
+ let predicate = obligation.predicate.clone().to_predicate(self.tcx);
+ let predicate = self.resolve_vars_if_possible(predicate);
+ self.report_overflow_error(
+ &predicate,
+ obligation.cause.span,
+ suggest_increasing_limit,
+ |err| {
+ self.note_obligation_cause_code(
+ err,
+ predicate,
+ obligation.param_env,
+ obligation.cause.code(),
+ &mut vec![],
+ &mut Default::default(),
+ );
+ },
+ );
+ }
+
fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
let suggested_limit = match self.tcx.recursion_limit() {
Limit(0) => Limit(2),
}
/// Reports that a cycle was detected which led to overflow and halts
- /// compilation. This is equivalent to `report_overflow_error` except
+ /// compilation. This is equivalent to `report_overflow_obligation` except
/// that we can give a more helpful error message (and, in particular,
/// we do not suggest increasing the overflow limit, which is not
/// going to help).
- fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+ fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
let cycle = self.resolve_vars_if_possible(cycle.to_owned());
assert!(!cycle.is_empty());
// The 'deepest' obligation is most likely to have a useful
// cause 'backtrace'
- self.report_overflow_error(cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), false);
+ self.report_overflow_obligation(
+ cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
+ false,
+ );
}
fn report_selection_error(
{
self.note_obligation_cause_code(
&mut diag,
- &error.obligation.predicate,
+ error.obligation.predicate,
error.obligation.param_env,
code,
&mut vec![],
diag.emit();
}
FulfillmentErrorCode::CodeCycle(ref cycle) => {
- self.report_overflow_error_cycle(cycle);
+ self.report_overflow_obligation_cycle(cycle);
}
}
}
| ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::OpaqueType
);
- let expected_ty = data.term.ty().unwrap();
+ let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
// constrain inference variables a bit more to nested obligations from normalize so
// we can have more helpful errors.
&self,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Vec<ImplCandidate<'tcx>> {
- self.tcx
+ let mut candidates: Vec<_> = self
+ .tcx
.all_impls(trait_pred.def_id())
.filter_map(|def_id| {
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
})
- .collect()
+ .collect();
+ if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
+ // If any of the candidates is a perfect match, we don't want to show all of them.
+ // This is particularly relevant for the case of numeric types (as they all have the
+ // same cathegory).
+ candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
+ }
+ candidates
}
fn report_similar_impl_candidates(
return report(normalized_impl_candidates, err);
}
- let normalize = |candidate| {
- let infcx = self.tcx.infer_ctxt().build();
- infcx
- .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
- .query_normalize(candidate)
- .map_or(candidate, |normalized| normalized.value)
- };
-
// Sort impl candidates so that ordering is consistent for UI tests.
// because the ordering of `impl_candidates` may not be deterministic:
// https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
let mut normalized_impl_candidates_and_similarities = impl_candidates
.into_iter()
.map(|ImplCandidate { trait_ref, similarity }| {
- let normalized = normalize(trait_ref);
+ // FIXME(compiler-errors): This should be using `NormalizeExt::normalize`
+ let normalized = self
+ .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+ .query_normalize(trait_ref)
+ .map_or(trait_ref, |normalized| normalized.value);
(similarity, normalized)
})
.collect::<Vec<_>>();
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
self.note_obligation_cause_code(
err,
- &obligation.predicate,
+ obligation.predicate,
obligation.param_env,
obligation.cause.code(),
&mut vec![],