MultiSpan, Style,
};
use rustc_hir as hir;
+use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::GenericParam;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::print::{FmtPrinter, Print};
use rustc_middle::ty::{
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
TypeVisitable,
suggest_increasing_limit: bool,
) -> !
where
- T: fmt::Display + TypeFoldable<'tcx>;
+ 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 suggest_new_overflow_limit(&self, err: &mut Diagnostic);
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
});
- let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]);
+ let trait_ref = self.tcx.mk_trait_ref(trait_def_id, [ty.skip_binder(), var]);
let obligation = Obligation::new(
self.tcx,
ObligationCause::dummy(),
param_env,
- ty.rebind(ty::TraitPredicate {
- trait_ref: ty::TraitRef::new(trait_def_id, substs),
- constness,
- polarity,
- }),
+ ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }),
);
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
fulfill_cx.register_predicate_obligation(self, obligation);
suggest_increasing_limit: bool,
) -> !
where
- T: fmt::Display + TypeFoldable<'tcx>,
+ 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,
{
let predicate = self.resolve_vars_if_possible(obligation.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.
+ pred_str = predicate
+ .print(FmtPrinter::new_with_limit(
+ self.tcx,
+ Namespace::TypeNS,
+ rustc_session::Limit(6),
+ ))
+ .unwrap()
+ .into_buffer();
+ }
let mut err = struct_span_err!(
self.tcx.sess,
obligation.cause.span,
E0275,
"overflow evaluating the requirement `{}`",
- predicate
+ pred_str,
);
if suggest_increasing_limit {
root_obligation: &PredicateObligation<'tcx>,
error: &SelectionError<'tcx>,
) {
- self.set_tainted_by_errors();
let tcx = self.tcx;
let mut span = obligation.cause.span;
+ // FIXME: statically guarantee this by tainting after the diagnostic is emitted
+ self.set_tainted_by_errors(
+ tcx.sess.delay_span_bug(span, "`report_selection_error` did not emit an error"),
+ );
let mut err = match *error {
SelectionError::Unimplemented => {
if trait_predicate.skip_binder().self_ty().is_never()
&& self.fallback_has_occurred
{
- let predicate = trait_predicate.map_bound(|mut trait_pred| {
- trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
- self.tcx.mk_unit(),
- &trait_pred.trait_ref.substs[1..],
- );
- trait_pred
+ let predicate = trait_predicate.map_bound(|trait_pred| {
+ trait_pred.with_self_type(self.tcx, self.tcx.mk_unit())
});
let unit_obligation = obligation.with(tcx, predicate);
if self.predicate_may_hold(&unit_obligation) {
)
}
+ ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
+
ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!(
span,
"TypeWellFormedFromEnv predicate should only exist in the environment"
ty::Bool => Some(0),
ty::Char => Some(1),
ty::Str => Some(2),
- ty::Adt(def, _) if tcx.is_diagnostic_item(sym::String, def.did()) => Some(2),
+ ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => Some(2),
ty::Int(..)
| ty::Uint(..)
| ty::Float(..)
param_env: ty::ParamEnv<'tcx>,
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
) -> PredicateObligation<'tcx> {
- let trait_pred = trait_ref_and_ty.map_bound_ref(|(tr, new_self_ty)| ty::TraitPredicate {
- trait_ref: ty::TraitRef {
- substs: self.tcx.mk_substs_trait(*new_self_ty, &tr.trait_ref.substs[1..]),
- ..tr.trait_ref
- },
- ..*tr
- });
+ let trait_pred = trait_ref_and_ty
+ .map_bound(|(tr, new_self_ty)| tr.with_self_type(self.tcx, new_self_ty));
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
}
// 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 !self.is_tainted_by_errors() {
+ if let None = self.tainted_by_errors() {
self.emit_inference_failure_err(
body_id,
span,
if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
} else {
- if self.is_tainted_by_errors() {
- err.delay_as_bug();
+ if self.tainted_by_errors().is_some() {
+ err.cancel();
return;
}
err.note(&format!("cannot satisfy `{}`", predicate));
}
}
_ => {
- if self.is_tainted_by_errors() {
- err.delay_as_bug();
+ if self.tainted_by_errors().is_some() {
+ err.cancel();
return;
}
err.note(&format!("cannot satisfy `{}`", predicate));
] = path.segments
&& data.trait_ref.def_id == *trait_id
&& self.tcx.trait_of_item(*item_id) == Some(*trait_id)
- && !self.is_tainted_by_errors()
+ && let None = self.tainted_by_errors()
{
let (verb, noun) = match self.tcx.associated_item(item_id).kind {
ty::AssocKind::Const => ("refer to the", "constant"),
// with error messages.
if arg.references_error()
|| self.tcx.sess.has_errors().is_some()
- || self.is_tainted_by_errors()
+ || self.tainted_by_errors().is_some()
{
return;
}
ty::PredicateKind::Subtype(data) => {
if data.references_error()
|| self.tcx.sess.has_errors().is_some()
- || self.is_tainted_by_errors()
+ || self.tainted_by_errors().is_some()
{
// no need to overload user in such cases
return;
self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true)
}
ty::PredicateKind::Projection(data) => {
- if predicate.references_error() || self.is_tainted_by_errors() {
+ if predicate.references_error() || self.tainted_by_errors().is_some() {
return;
}
let subst = data
}
ty::PredicateKind::ConstEvaluatable(data) => {
- if predicate.references_error() || self.is_tainted_by_errors() {
+ if predicate.references_error() || self.tainted_by_errors().is_some() {
return;
}
let subst = data.walk().find(|g| g.is_non_region_infer());
}
}
_ => {
- if self.tcx.sess.has_errors().is_some() || self.is_tainted_by_errors() {
+ if self.tcx.sess.has_errors().is_some() || self.tainted_by_errors().is_some() {
return;
}
let mut err = struct_span_err!(
post.sort();
post.dedup();
- if self.is_tainted_by_errors()
+ if self.tainted_by_errors().is_some()
&& (crate_names.len() == 1
&& spans.len() == 0
&& ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())