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