use rustc_hir::lang_items::LangItem;
use rustc_hir::Node;
use rustc_middle::dep_graph::DepContext;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
use std::{cmp, fmt, iter};
mod note;
+mod note_and_explain;
mod suggest;
pub(crate) mod need_type_info;
}
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
- let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
- let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
+ let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
+ let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
let mut values = self.cmp_fn_sig(&sig1, &sig2);
let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
}
(ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
- let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
+ let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
let mut values = self.cmp_fn_sig(&sig1, sig2);
values.0.push_highlighted(format!(
" {{{}}}",
}
(ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
- let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
+ let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
let mut values = self.cmp_fn_sig(sig1, &sig2);
values.1.push_normal(format!(
" {{{}}}",
{
format!("expected this to be `{}`", expected)
} else {
- terr.to_string()
+ terr.to_string(self.tcx).to_string()
};
label_or_note(sp, &terr);
label_or_note(span, &msg);
} else {
- label_or_note(span, &terr.to_string());
+ label_or_note(span, &terr.to_string(self.tcx));
label_or_note(sp, &msg);
}
} else {
- label_or_note(span, &terr.to_string());
+ if let Some(values) = values
+ && let Some((e, f)) = values.ty()
+ && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
+ {
+ let e = self.tcx.erase_regions(e);
+ let f = self.tcx.erase_regions(f);
+ let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
+ let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
+ if expected == found {
+ label_or_note(span, &terr.to_string(self.tcx));
+ } else {
+ label_or_note(span, &format!("expected {expected}, found {found}"));
+ }
+ } else {
+ label_or_note(span, &terr.to_string(self.tcx));
+ }
}
if let Some((expected, found, exp_p, found_p)) = expected_found {
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
+ self.suggest_function_pointers(cause, span, &exp_found, diag);
}
}
- // In some (most?) cases cause.body_id points to actual body, but in some cases
- // it's an actual definition. According to the comments (e.g. in
- // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter
- // is relied upon by some other code. This might (or might not) need cleanup.
- let body_owner_def_id =
- self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
- self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
- });
self.check_and_note_conflicting_crates(diag, terr);
- self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
+
+ self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
+ if let Some(exp_found) = exp_found
+ && let exp_found = TypeError::Sorts(exp_found)
+ && exp_found != terr
+ {
+ self.note_and_explain_type_err(
+ diag,
+ exp_found,
+ cause,
+ span,
+ cause.body_id.to_def_id(),
+ );
+ }
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
- pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+ pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
let (a, b) = self.resolve_vars_if_possible((a, b));
SameTypeModuloInfer(self).relate(a, b).is_ok()
}