rustc_trait_selection/error_reporting/traits/
ambiguity.rs

1use std::ops::ControlFlow;
2
3use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_span_code_err};
4use rustc_hir as hir;
5use rustc_hir::LangItem;
6use rustc_hir::def::{DefKind, Res};
7use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
8use rustc_hir::intravisit::Visitor as _;
9use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
10use rustc_infer::traits::util::elaborate;
11use rustc_infer::traits::{
12    Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation,
13};
14use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _};
15use rustc_session::parse::feature_err_unstable_feature_bound;
16use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
17use tracing::{debug, instrument};
18
19use crate::error_reporting::TypeErrCtxt;
20use crate::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
21use crate::error_reporting::traits::{FindExprBySpan, to_pretty_impl_header};
22use crate::traits::ObligationCtxt;
23use crate::traits::query::evaluate_obligation::InferCtxtExt;
24
25#[derive(Debug)]
26pub enum CandidateSource {
27    DefId(DefId),
28    ParamEnv(Span),
29}
30
31pub fn compute_applicable_impls_for_diagnostics<'tcx>(
32    infcx: &InferCtxt<'tcx>,
33    obligation: &PolyTraitObligation<'tcx>,
34) -> Vec<CandidateSource> {
35    let tcx = infcx.tcx;
36    let param_env = obligation.param_env;
37
38    let predicate_polarity = obligation.predicate.skip_binder().polarity;
39
40    let impl_may_apply = |impl_def_id| {
41        let ocx = ObligationCtxt::new(infcx);
42        infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
43            let obligation_trait_ref = ocx.normalize(
44                &ObligationCause::dummy(),
45                param_env,
46                placeholder_obligation.trait_ref,
47            );
48
49            let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
50            let impl_trait_ref =
51                tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
52            let impl_trait_ref =
53                ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
54
55            if let Err(_) =
56                ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
57            {
58                return false;
59            }
60
61            let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
62            let impl_polarity = impl_trait_header.polarity;
63
64            match (impl_polarity, predicate_polarity) {
65                (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
66                | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {}
67                _ => return false,
68            }
69
70            let obligations = tcx
71                .predicates_of(impl_def_id)
72                .instantiate(tcx, impl_args)
73                .into_iter()
74                .map(|(predicate, _)| {
75                    Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
76                })
77                // Kinda hacky, but let's just throw away obligations that overflow.
78                // This may reduce the accuracy of this check (if the obligation guides
79                // inference or it actually resulted in error after others are processed)
80                // ... but this is diagnostics code.
81                .filter(|obligation| {
82                    infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok()
83                });
84            ocx.register_obligations(obligations);
85
86            ocx.select_where_possible().is_empty()
87        })
88    };
89
90    let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
91        let ocx = ObligationCtxt::new(infcx);
92        infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
93            let obligation_trait_ref = ocx.normalize(
94                &ObligationCause::dummy(),
95                param_env,
96                placeholder_obligation.trait_ref,
97            );
98
99            let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
100                DUMMY_SP,
101                BoundRegionConversionTime::HigherRankedType,
102                poly_trait_predicate,
103            );
104            let param_env_trait_ref =
105                ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
106
107            if let Err(_) = ocx.eq(
108                &ObligationCause::dummy(),
109                param_env,
110                obligation_trait_ref,
111                param_env_trait_ref,
112            ) {
113                return false;
114            }
115
116            ocx.select_where_possible().is_empty()
117        })
118    };
119
120    let mut ambiguities = Vec::new();
121
122    tcx.for_each_relevant_impl(
123        obligation.predicate.def_id(),
124        obligation.predicate.skip_binder().trait_ref.self_ty(),
125        |impl_def_id| {
126            if infcx.probe(|_| impl_may_apply(impl_def_id)) {
127                ambiguities.push(CandidateSource::DefId(impl_def_id))
128            }
129        },
130    );
131
132    // If our `body_id` has been set (and isn't just from a dummy obligation cause),
133    // then try to look for a param-env clause that would apply. The way we compute
134    // this is somewhat manual, since we need the spans, so we elaborate this directly
135    // from `predicates_of` rather than actually looking at the param-env which
136    // otherwise would be more appropriate.
137    let body_id = obligation.cause.body_id;
138    if body_id != CRATE_DEF_ID {
139        let predicates = tcx.predicates_of(body_id.to_def_id()).instantiate_identity(tcx);
140        for (pred, span) in elaborate(tcx, predicates.into_iter()) {
141            let kind = pred.kind();
142            if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
143                && param_env_candidate_may_apply(kind.rebind(trait_pred))
144            {
145                if kind.rebind(trait_pred.trait_ref)
146                    == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
147                {
148                    ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
149                } else {
150                    ambiguities.push(CandidateSource::ParamEnv(span))
151                }
152            }
153        }
154    }
155
156    ambiguities
157}
158
159impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
160    #[instrument(skip(self), level = "debug")]
161    pub(super) fn maybe_report_ambiguity(
162        &self,
163        obligation: &PredicateObligation<'tcx>,
164    ) -> ErrorGuaranteed {
165        // Unable to successfully determine, probably means
166        // insufficient type information, but could mean
167        // ambiguous impls. The latter *ought* to be a
168        // coherence violation, so we don't report it here.
169
170        let predicate = self.resolve_vars_if_possible(obligation.predicate);
171        let span = obligation.cause.span;
172        let mut long_ty_path = None;
173
174        debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
175
176        // Ambiguity errors are often caused as fallout from earlier errors.
177        // We ignore them if this `infcx` is tainted in some cases below.
178
179        let bound_predicate = predicate.kind();
180        let mut err = match bound_predicate.skip_binder() {
181            ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
182                let trait_pred = bound_predicate.rebind(data);
183                debug!(?trait_pred);
184
185                if let Err(e) = predicate.error_reported() {
186                    return e;
187                }
188
189                if let Err(guar) = self.tcx.ensure_ok().coherent_trait(trait_pred.def_id()) {
190                    // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
191                    // other `Foo` impls are incoherent.
192                    return guar;
193                }
194
195                // This is kind of a hack: it frequently happens that some earlier
196                // error prevents types from being fully inferred, and then we get
197                // a bunch of uninteresting errors saying something like "<generic
198                // #0> doesn't implement Sized". It may even be true that we
199                // could just skip over all checks where the self-ty is an
200                // inference variable, but I was afraid that there might be an
201                // inference variable created, registered as an obligation, and
202                // then never forced by writeback, and hence by skipping here we'd
203                // be ignoring the fact that we don't KNOW the type works
204                // out. Though even that would probably be harmless, given that
205                // we're only talking about builtin traits, which are known to be
206                // inhabited. We used to check for `self.tainted_by_errors()` to
207                // avoid inundating the user with unnecessary errors, but we now
208                // check upstream for type errors and don't add the obligations to
209                // begin with in those cases.
210                if matches!(
211                    self.tcx.as_lang_item(trait_pred.def_id()),
212                    Some(LangItem::Sized | LangItem::MetaSized)
213                ) {
214                    return match self.tainted_by_errors() {
215                        None => self
216                            .emit_inference_failure_err(
217                                obligation.cause.body_id,
218                                span,
219                                trait_pred.self_ty().skip_binder().into(),
220                                TypeAnnotationNeeded::E0282,
221                                false,
222                            )
223                            .emit(),
224                        Some(e) => e,
225                    };
226                }
227
228                // Typically, this ambiguity should only happen if
229                // there are unresolved type inference variables
230                // (otherwise it would suggest a coherence
231                // failure). But given #21974 that is not necessarily
232                // the case -- we can have multiple where clauses that
233                // are only distinguished by a region, which results
234                // in an ambiguity even when all types are fully
235                // known, since we don't dispatch based on region
236                // relationships.
237
238                // Pick the first generic parameter that still contains inference variables as the one
239                // we're going to emit an error for. If there are none (see above), fall back to
240                // a more general error.
241                let term = data
242                    .trait_ref
243                    .args
244                    .iter()
245                    .filter_map(ty::GenericArg::as_term)
246                    .find(|s| s.has_non_region_infer());
247
248                let mut err = if let Some(term) = term {
249                    self.emit_inference_failure_err(
250                        obligation.cause.body_id,
251                        span,
252                        term,
253                        TypeAnnotationNeeded::E0283,
254                        true,
255                    )
256                } else {
257                    struct_span_code_err!(
258                        self.dcx(),
259                        span,
260                        E0283,
261                        "type annotations needed: cannot satisfy `{}`",
262                        self.tcx.short_string(predicate, &mut long_ty_path),
263                    )
264                    .with_long_ty_path(long_ty_path)
265                };
266
267                let mut ambiguities = compute_applicable_impls_for_diagnostics(
268                    self.infcx,
269                    &obligation.with(self.tcx, trait_pred),
270                );
271                let has_non_region_infer = trait_pred
272                    .skip_binder()
273                    .trait_ref
274                    .args
275                    .types()
276                    .any(|t| !t.is_ty_or_numeric_infer());
277                // It doesn't make sense to talk about applicable impls if there are more than a
278                // handful of them. If there are a lot of them, but only a few of them have no type
279                // params, we only show those, as they are more likely to be useful/intended.
280                if ambiguities.len() > 5 {
281                    let infcx = self.infcx;
282                    if !ambiguities.iter().all(|option| match option {
283                        CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
284                        CandidateSource::ParamEnv(_) => true,
285                    }) {
286                        // If not all are blanket impls, we filter blanked impls out.
287                        ambiguities.retain(|option| match option {
288                            CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
289                            CandidateSource::ParamEnv(_) => true,
290                        });
291                    }
292                }
293                if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
294                    if let Some(e) = self.tainted_by_errors()
295                        && term.is_none()
296                    {
297                        // If `arg.is_none()`, then this is probably two param-env
298                        // candidates or impl candidates that are equal modulo lifetimes.
299                        // Therefore, if we've already emitted an error, just skip this
300                        // one, since it's not particularly actionable.
301                        err.cancel();
302                        return e;
303                    }
304                    self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
305                } else {
306                    if let Some(e) = self.tainted_by_errors() {
307                        err.cancel();
308                        return e;
309                    }
310                    let pred = self.tcx.short_string(predicate, &mut err.long_ty_path());
311                    err.note(format!("cannot satisfy `{pred}`"));
312                    let impl_candidates =
313                        self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
314                    if impl_candidates.len() < 40 {
315                        self.report_similar_impl_candidates(
316                            impl_candidates.as_slice(),
317                            trait_pred,
318                            obligation.cause.body_id,
319                            &mut err,
320                            false,
321                            obligation.param_env,
322                        );
323                    }
324                }
325
326                if let ObligationCauseCode::WhereClause(def_id, _)
327                | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
328                {
329                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
330                }
331
332                if term.is_some_and(|term| term.as_type().is_some())
333                    && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id)
334                {
335                    let mut expr_finder = FindExprBySpan::new(span, self.tcx);
336                    expr_finder.visit_expr(&body.value);
337
338                    if let Some(hir::Expr {
339                        kind:
340                            hir::ExprKind::Call(
341                                hir::Expr {
342                                    kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
343                                    ..
344                                },
345                                _,
346                            )
347                            | hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
348                        ..
349                    }) = expr_finder.result
350                        && let [
351                            ..,
352                            trait_path_segment @ hir::PathSegment {
353                                res: Res::Def(DefKind::Trait, trait_id),
354                                ..
355                            },
356                            hir::PathSegment {
357                                ident: assoc_item_ident,
358                                res: Res::Def(_, item_id),
359                                ..
360                            },
361                        ] = path.segments
362                        && data.trait_ref.def_id == *trait_id
363                        && self.tcx.trait_of_assoc(*item_id) == Some(*trait_id)
364                        && let None = self.tainted_by_errors()
365                    {
366                        let assoc_item = self.tcx.associated_item(item_id);
367                        let (verb, noun) = match assoc_item.kind {
368                            ty::AssocKind::Const { .. } => ("refer to the", "constant"),
369                            ty::AssocKind::Fn { .. } => ("call", "function"),
370                            // This is already covered by E0223, but this following single match
371                            // arm doesn't hurt here.
372                            ty::AssocKind::Type { .. } => ("refer to the", "type"),
373                        };
374
375                        // Replace the more general E0283 with a more specific error
376                        err.cancel();
377                        err = self.dcx().struct_span_err(
378                            span,
379                            format!(
380                                "cannot {verb} associated {noun} on trait without specifying the \
381                                 corresponding `impl` type",
382                            ),
383                        );
384                        err.code(E0790);
385
386                        if item_id.is_local() {
387                            let trait_ident = self.tcx.item_name(*trait_id);
388                            err.span_label(
389                                self.tcx.def_span(*item_id),
390                                format!("`{trait_ident}::{assoc_item_ident}` defined here"),
391                            );
392                        }
393
394                        err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
395
396                        let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
397
398                        if let Some(impl_def_id) =
399                            trait_impls.non_blanket_impls().values().flatten().next()
400                        {
401                            let non_blanket_impl_count =
402                                trait_impls.non_blanket_impls().values().flatten().count();
403                            // If there is only one implementation of the trait, suggest using it.
404                            // Otherwise, use a placeholder comment for the implementation.
405                            let (message, self_types) = if non_blanket_impl_count == 1 {
406                                (
407                                    "use the fully-qualified path to the only available \
408                                     implementation",
409                                    vec![format!(
410                                        "{}",
411                                        self.tcx.type_of(impl_def_id).instantiate_identity()
412                                    )],
413                                )
414                            } else if non_blanket_impl_count < 20 {
415                                (
416                                    "use a fully-qualified path to one of the available \
417                                     implementations",
418                                    trait_impls
419                                        .non_blanket_impls()
420                                        .values()
421                                        .flatten()
422                                        .map(|id| {
423                                            format!(
424                                                "{}",
425                                                self.tcx.type_of(id).instantiate_identity()
426                                            )
427                                        })
428                                        .collect::<Vec<String>>(),
429                                )
430                            } else {
431                                (
432                                    "use a fully-qualified path to a specific available \
433                                     implementation",
434                                    vec!["/* self type */".to_string()],
435                                )
436                            };
437                            let suggestions: Vec<_> = self_types
438                                .into_iter()
439                                .map(|self_type| {
440                                    let mut suggestions = vec![(
441                                        path.span.shrink_to_lo(),
442                                        format!("<{self_type} as "),
443                                    )];
444                                    if let Some(generic_arg) = trait_path_segment.args {
445                                        let between_span = trait_path_segment
446                                            .ident
447                                            .span
448                                            .between(generic_arg.span_ext);
449                                        // get rid of :: between Trait and <type>
450                                        // must be '::' between them, otherwise the parser won't accept the code
451                                        suggestions.push((between_span, "".to_string()));
452                                        suggestions.push((
453                                            generic_arg.span_ext.shrink_to_hi(),
454                                            ">".to_string(),
455                                        ));
456                                    } else {
457                                        suggestions.push((
458                                            trait_path_segment.ident.span.shrink_to_hi(),
459                                            ">".to_string(),
460                                        ));
461                                    }
462                                    suggestions
463                                })
464                                .collect();
465                            err.multipart_suggestions(
466                                message,
467                                suggestions,
468                                Applicability::MaybeIncorrect,
469                            );
470                        }
471                    }
472                };
473
474                err
475            }
476
477            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
478                // Same hacky approach as above to avoid deluging user
479                // with error messages.
480
481                if let Err(e) = term.error_reported() {
482                    return e;
483                }
484                if let Some(e) = self.tainted_by_errors() {
485                    return e;
486                }
487
488                self.emit_inference_failure_err(
489                    obligation.cause.body_id,
490                    span,
491                    term,
492                    TypeAnnotationNeeded::E0282,
493                    false,
494                )
495            }
496
497            ty::PredicateKind::Subtype(data) => {
498                if let Err(e) = data.error_reported() {
499                    return e;
500                }
501                if let Some(e) = self.tainted_by_errors() {
502                    return e;
503                }
504                let ty::SubtypePredicate { a_is_expected: _, a, b } = data;
505                // both must be type variables, or the other would've been instantiated
506                assert!(a.is_ty_var() && b.is_ty_var());
507                self.emit_inference_failure_err(
508                    obligation.cause.body_id,
509                    span,
510                    a.into(),
511                    TypeAnnotationNeeded::E0282,
512                    true,
513                )
514            }
515
516            ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
517                if let Err(e) = predicate.error_reported() {
518                    return e;
519                }
520                if let Some(e) = self.tainted_by_errors() {
521                    return e;
522                }
523
524                if let Err(guar) = self
525                    .tcx
526                    .ensure_ok()
527                    .coherent_trait(self.tcx.parent(data.projection_term.def_id))
528                {
529                    // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
530                    // other `Foo` impls are incoherent.
531                    return guar;
532                }
533                let term = data
534                    .projection_term
535                    .args
536                    .iter()
537                    .filter_map(ty::GenericArg::as_term)
538                    .chain([data.term])
539                    .find(|g| g.has_non_region_infer());
540                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
541                if let Some(term) = term {
542                    self.emit_inference_failure_err(
543                        obligation.cause.body_id,
544                        span,
545                        term,
546                        TypeAnnotationNeeded::E0284,
547                        true,
548                    )
549                    .with_note(format!("cannot satisfy `{predicate}`"))
550                    .with_long_ty_path(long_ty_path)
551                } else {
552                    // If we can't find a generic parameter, just print a generic error
553                    struct_span_code_err!(
554                        self.dcx(),
555                        span,
556                        E0284,
557                        "type annotations needed: cannot satisfy `{predicate}`",
558                    )
559                    .with_span_label(span, format!("cannot satisfy `{predicate}`"))
560                    .with_long_ty_path(long_ty_path)
561                }
562            }
563
564            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
565                if let Err(e) = predicate.error_reported() {
566                    return e;
567                }
568                if let Some(e) = self.tainted_by_errors() {
569                    return e;
570                }
571                let term =
572                    data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
573                if let Some(term) = term {
574                    self.emit_inference_failure_err(
575                        obligation.cause.body_id,
576                        span,
577                        term,
578                        TypeAnnotationNeeded::E0284,
579                        true,
580                    )
581                } else {
582                    // If we can't find a generic parameter, just print a generic error
583                    let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
584                    struct_span_code_err!(
585                        self.dcx(),
586                        span,
587                        E0284,
588                        "type annotations needed: cannot satisfy `{predicate}`",
589                    )
590                    .with_span_label(span, format!("cannot satisfy `{predicate}`"))
591                    .with_long_ty_path(long_ty_path)
592                }
593            }
594
595            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
596                .emit_inference_failure_err(
597                    obligation.cause.body_id,
598                    span,
599                    ct.into(),
600                    TypeAnnotationNeeded::E0284,
601                    true,
602                ),
603
604            ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
605                if term.is_infer() =>
606            {
607                if let Some(e) = self.tainted_by_errors() {
608                    return e;
609                }
610                let alias = self.tcx.short_string(alias, &mut long_ty_path);
611                struct_span_code_err!(
612                    self.dcx(),
613                    span,
614                    E0284,
615                    "type annotations needed: cannot normalize `{alias}`",
616                )
617                .with_span_label(span, format!("cannot normalize `{alias}`"))
618                .with_long_ty_path(long_ty_path)
619            }
620
621            ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
622                if let Some(e) = self.tainted_by_errors() {
623                    return e;
624                }
625
626                if self.tcx.features().staged_api() {
627                    self.dcx().struct_span_err(
628                        span,
629                        format!("unstable feature `{sym}` is used without being enabled."),
630                    ).with_help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"))
631                } else {
632                    feature_err_unstable_feature_bound(
633                        &self.tcx.sess,
634                        sym,
635                        span,
636                        format!("use of unstable library feature `{sym}`"),
637                    )
638                }
639            }
640
641            _ => {
642                if let Some(e) = self.tainted_by_errors() {
643                    return e;
644                }
645                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
646                struct_span_code_err!(
647                    self.dcx(),
648                    span,
649                    E0284,
650                    "type annotations needed: cannot satisfy `{predicate}`",
651                )
652                .with_span_label(span, format!("cannot satisfy `{predicate}`"))
653                .with_long_ty_path(long_ty_path)
654            }
655        };
656        self.note_obligation_cause(&mut err, obligation);
657        err.emit()
658    }
659
660    fn annotate_source_of_ambiguity(
661        &self,
662        err: &mut Diag<'_>,
663        ambiguities: &[CandidateSource],
664        predicate: ty::Predicate<'tcx>,
665    ) {
666        let mut spans = vec![];
667        let mut crates = vec![];
668        let mut post = vec![];
669        let mut has_param_env = false;
670        for ambiguity in ambiguities {
671            match ambiguity {
672                CandidateSource::DefId(impl_def_id) => match self.tcx.span_of_impl(*impl_def_id) {
673                    Ok(span) => spans.push(span),
674                    Err(name) => {
675                        crates.push(name);
676                        if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
677                            post.push(header);
678                        }
679                    }
680                },
681                CandidateSource::ParamEnv(span) => {
682                    has_param_env = true;
683                    spans.push(*span);
684                }
685            }
686        }
687        let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{n}`")).collect();
688        crate_names.sort();
689        crate_names.dedup();
690        post.sort();
691        post.dedup();
692
693        if self.tainted_by_errors().is_some()
694            && (crate_names.len() == 1
695                && spans.len() == 0
696                && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
697                || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
698        {
699            // Avoid complaining about other inference issues for expressions like
700            // `42 >> 1`, where the types are still `{integer}`, but we want to
701            // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too?
702            // NOTE(eddyb) this was `.cancel()`, but `err`
703            // is borrowed, so we can't fully defuse it.
704            err.downgrade_to_delayed_bug();
705            return;
706        }
707
708        let msg = format!(
709            "multiple `impl`s{} satisfying `{}` found",
710            if has_param_env { " or `where` clauses" } else { "" },
711            predicate
712        );
713        let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
714            format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::<Vec<_>>().join("\n"),)
715        } else if post.len() == 1 {
716            format!(": `{}`", post[0])
717        } else {
718            String::new()
719        };
720
721        match (spans.len(), crates.len(), crate_names.len()) {
722            (0, 0, 0) => {
723                err.note(format!("cannot satisfy `{predicate}`"));
724            }
725            (0, _, 1) => {
726                err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,));
727            }
728            (0, _, _) => {
729                err.note(format!(
730                    "{} in the following crates: {}{}",
731                    msg,
732                    crate_names.join(", "),
733                    post,
734                ));
735            }
736            (_, 0, 0) => {
737                let span: MultiSpan = spans.into();
738                err.span_note(span, msg);
739            }
740            (_, 1, 1) => {
741                let span: MultiSpan = spans.into();
742                err.span_note(span, msg);
743                err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,));
744            }
745            _ => {
746                let span: MultiSpan = spans.into();
747                err.span_note(span, msg);
748                err.note(format!(
749                    "and more `impl`s found in the following crates: {}{}",
750                    crate_names.join(", "),
751                    post,
752                ));
753            }
754        }
755    }
756}
757
758struct HasNumericInferVisitor;
759
760impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
761    type Result = ControlFlow<()>;
762
763    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
764        if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) {
765            ControlFlow::Break(())
766        } else {
767            ControlFlow::Continue(())
768        }
769    }
770}