- let obligation = Obligation::new(
- obligation.cause.clone(),
- obligation.param_env,
- new_trait_ref.to_predicate(),
- );
- match self.evaluate_obligation(&obligation) {
- Ok(EvaluationResult::EvaluatedToOk) |
- Ok(EvaluationResult::EvaluatedToOkModuloRegions) |
- Ok(EvaluationResult::EvaluatedToAmbig) => {
- if let Some(hir::Node::Item(hir::Item {
- ident,
- kind: hir::ItemKind::Fn(.., body_id),
- ..
- })) = self.tcx.hir().get_if_local(def_id) {
- let body = self.tcx.hir().body(*body_id);
- let msg = "use parentheses to call the function";
- let snippet = format!(
- "{}({})",
- ident,
- body.params.iter()
- .map(|arg| match &arg.pat.kind {
- hir::PatKind::Binding(_, _, ident, None)
- if ident.name != kw::SelfLower => ident.to_string(),
- _ => "_".to_string(),
- }).collect::<Vec<_>>().join(", "),
- );
- // When the obligation error has been ensured to have been caused by
- // an argument, the `obligation.cause.span` points at the expression
- // of the argument, so we can provide a suggestion. This is signaled
- // by `points_at_arg`. Otherwise, we give a more general note.
- if points_at_arg {
- err.span_suggestion(
- obligation.cause.span,
- msg,
- snippet,
- Applicability::HasPlaceholders,
- );
- } else {
- err.help(&format!("{}: `{}`", msg, snippet));
- }
- }
+ let args = decl.inputs.iter()
+ .map(|_| "_")
+ .collect::<Vec<_>>()
+ .join(", ");
+ format!("{}({})", name, args)
+ }
+ Some(hir::Node::Item(hir::Item {
+ ident,
+ kind: hir::ItemKind::Fn(.., body_id),
+ ..
+ })) => {
+ err.span_label(ident.span, "consider calling this function");
+ let body = hir.body(*body_id);
+ let args = body.params.iter()
+ .map(|arg| match &arg.pat.kind {
+ hir::PatKind::Binding(_, _, ident, None)
+ // FIXME: provide a better suggestion when encountering `SelfLower`, it
+ // should suggest a method call.
+ if ident.name != kw::SelfLower => ident.to_string(),
+ _ => "_".to_string(),
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+ format!("{}({})", ident, args)
+ }
+ _ => return,
+ };
+ if points_at_arg {
+ // When the obligation error has been ensured to have been caused by
+ // an argument, the `obligation.cause.span` points at the expression
+ // of the argument, so we can provide a suggestion. This is signaled
+ // by `points_at_arg`. Otherwise, we give a more general note.
+ err.span_suggestion(
+ obligation.cause.span,
+ &msg,
+ snippet,
+ Applicability::HasPlaceholders,
+ );
+ } else {
+ err.help(&format!("{}: `{}`", msg, snippet));
+ }
+ }
+
+ fn suggest_add_reference_to_arg(
+ &self,
+ obligation: &PredicateObligation<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx>,
+ trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+ points_at_arg: bool,
+ has_custom_message: bool,
+ ) -> bool {
+ if !points_at_arg {
+ return false;
+ }
+
+ let span = obligation.cause.span;
+ let param_env = obligation.param_env;
+ let trait_ref = trait_ref.skip_binder();
+
+ if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+ // Try to apply the original trait binding obligation by borrowing.
+ let self_ty = trait_ref.self_ty();
+ let found = self_ty.to_string();
+ let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
+ let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
+ let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
+ let new_obligation = Obligation::new(
+ ObligationCause::dummy(),
+ param_env,
+ new_trait_ref.to_predicate(),
+ );
+ if self.predicate_must_hold_modulo_regions(&new_obligation) {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+ // We have a very specific type of error, where just borrowing this argument
+ // might solve the problem. In cases like this, the important part is the
+ // original type obligation, not the last one that failed, which is arbitrary.
+ // Because of this, we modify the error to refer to the original obligation and
+ // return early in the caller.
+ let msg = format!(
+ "the trait bound `{}: {}` is not satisfied",
+ found,
+ obligation.parent_trait_ref.skip_binder(),
+ );
+ if has_custom_message {
+ err.note(&msg);
+ } else {
+ err.message = vec![(msg, Style::NoStyle)];
+ }
+ if snippet.starts_with('&') {
+ // This is already a literal borrow and the obligation is failing
+ // somewhere else in the obligation chain. Do not suggest non-sense.
+ return false;