use super::InferCtxtPrivExt;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use rustc_middle::ty::print::with_no_trimmed_paths;
#[derive(Debug)]
pub enum GeneratorInteriorOrUpvar {
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
points_at_arg: bool,
);
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
points_at_arg: bool,
has_custom_message: bool,
) -> bool;
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
);
fn suggest_change_mut(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
points_at_arg: bool,
);
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
span: Span,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
);
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>;
err: &mut DiagnosticBuilder<'_>,
span: Span,
obligation: &PredicateObligation<'tcx>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
) -> bool;
fn point_at_returns_when_relevant(
&self,
err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
span: Span,
);
}
{
// Missing generic type parameter bound.
let param_name = self_ty.to_string();
- let constraint = trait_ref.print_only_trait_path().to_string();
+ let constraint =
+ with_no_trimmed_paths(|| trait_ref.print_only_trait_path().to_string());
if suggest_constraining_type_param(
self.tcx,
generics,
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
points_at_arg: bool,
) {
let self_ty = match trait_ref.self_ty().no_bound_vars() {
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
points_at_arg: bool,
has_custom_message: bool,
) -> bool {
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
) {
let span = obligation.cause.span;
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
points_at_arg: bool,
) {
let span = obligation.cause.span;
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>,
span: Span,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
) {
let is_empty_tuple =
- |ty: ty::Binder<Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
+ |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
let hir = self.tcx.hir();
let parent_node = hir.get_parent_node(obligation.cause.body_id);
err: &mut DiagnosticBuilder<'_>,
span: Span,
obligation: &PredicateObligation<'tcx>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
) -> bool {
match obligation.cause.code.peel_derives() {
// Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
| ObligationCauseCode::MethodReceiver
| ObligationCauseCode::ReturnNoExpression
| ObligationCauseCode::UnifyReceiver(..)
+ | ObligationCauseCode::OpaqueType
| ObligationCauseCode::MiscObligation => {}
ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type");
// Don't print the tuple of capture types
if !is_upvar_tys_infer_tuple {
- err.note(&format!("required because it appears within the type `{}`", ty));
+ let msg = format!("required because it appears within the type `{}`", ty);
+ match ty.kind() {
+ ty::Adt(def, _) => match self.tcx.opt_item_name(def.did) {
+ Some(ident) => err.span_note(ident.span, &msg),
+ None => err.note(&msg),
+ },
+ _ => err.note(&msg),
+ };
}
obligated_types.push(ty);
ObligationCauseCode::ImplDerivedObligation(ref data) => {
let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
let parent_def_id = parent_trait_ref.def_id();
- err.note(&format!(
+ let msg = format!(
"required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref.print_only_trait_path(),
parent_trait_ref.skip_binder().self_ty()
- ));
+ );
+ let mut candidates = vec![];
+ self.tcx.for_each_relevant_impl(
+ parent_def_id,
+ parent_trait_ref.self_ty().skip_binder(),
+ |impl_def_id| {
+ candidates.push(impl_def_id);
+ },
+ );
+ match &candidates[..] {
+ [def_id] => match self.tcx.hir().get_if_local(*def_id) {
+ Some(Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
+ ..
+ })) => {
+ let mut spans = Vec::with_capacity(2);
+ if let Some(trait_ref) = of_trait {
+ spans.push(trait_ref.path.span);
+ }
+ spans.push(self_ty.span);
+ err.span_note(spans, &msg)
+ }
+ _ => err.note(&msg),
+ },
+ _ => err.note(&msg),
+ };
let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx);
let mut data = data;
)
});
}
- ObligationCauseCode::CompareImplMethodObligation { .. } => {
- err.note(&format!(
- "the requirement `{}` appears on the impl method but not on the corresponding \
- trait method",
- predicate
- ));
+ ObligationCauseCode::CompareImplMethodObligation {
+ item_name,
+ trait_item_def_id,
+ ..
+ } => {
+ let msg = format!(
+ "the requirement `{}` appears on the impl method `{}` but not on the \
+ corresponding trait method",
+ predicate, item_name,
+ );
+ let sp = self
+ .tcx
+ .opt_item_name(trait_item_def_id)
+ .map(|i| i.span)
+ .unwrap_or_else(|| self.tcx.def_span(trait_item_def_id));
+ let mut assoc_span: MultiSpan = sp.into();
+ assoc_span.push_span_label(
+ sp,
+ format!("this trait method doesn't have the requirement `{}`", predicate),
+ );
+ if let Some(ident) = self
+ .tcx
+ .opt_associated_item(trait_item_def_id)
+ .and_then(|i| self.tcx.opt_item_name(i.container.id()))
+ {
+ assoc_span.push_span_label(ident.span, "in this trait".into());
+ }
+ err.span_note(assoc_span, &msg);
}
- ObligationCauseCode::CompareImplTypeObligation { .. } => {
- err.note(&format!(
- "the requirement `{}` appears on the associated impl type but not on the \
+ ObligationCauseCode::CompareImplTypeObligation {
+ item_name, trait_item_def_id, ..
+ } => {
+ let msg = format!(
+ "the requirement `{}` appears on the associated impl type `{}` but not on the \
corresponding associated trait type",
- predicate
- ));
+ predicate, item_name,
+ );
+ let sp = self.tcx.def_span(trait_item_def_id);
+ let mut assoc_span: MultiSpan = sp.into();
+ assoc_span.push_span_label(
+ sp,
+ format!(
+ "this trait associated type doesn't have the requirement `{}`",
+ predicate,
+ ),
+ );
+ if let Some(ident) = self
+ .tcx
+ .opt_associated_item(trait_item_def_id)
+ .and_then(|i| self.tcx.opt_item_name(i.container.id()))
+ {
+ assoc_span.push_span_label(ident.span, "in this trait".into());
+ }
+ err.span_note(assoc_span, &msg);
}
ObligationCauseCode::CompareImplConstObligation => {
err.note(&format!(
&self,
err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
- trait_ref: ty::Binder<ty::TraitRef<'tcx>>,
+ trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
span: Span,
) {
debug!(