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 file = 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                    match self.tainted_by_errors() {
215                        None => {
216                            let err = self.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                            return err.emit();
224                        }
225                        Some(e) => return e,
226                    }
227                }
228
229                // Typically, this ambiguity should only happen if
230                // there are unresolved type inference variables
231                // (otherwise it would suggest a coherence
232                // failure). But given #21974 that is not necessarily
233                // the case -- we can have multiple where clauses that
234                // are only distinguished by a region, which results
235                // in an ambiguity even when all types are fully
236                // known, since we don't dispatch based on region
237                // relationships.
238
239                // Pick the first generic parameter that still contains inference variables as the one
240                // we're going to emit an error for. If there are none (see above), fall back to
241                // a more general error.
242                let term = data
243                    .trait_ref
244                    .args
245                    .iter()
246                    .filter_map(ty::GenericArg::as_term)
247                    .find(|s| s.has_non_region_infer());
248
249                let mut err = if let Some(term) = term {
250                    self.emit_inference_failure_err(
251                        obligation.cause.body_id,
252                        span,
253                        term,
254                        TypeAnnotationNeeded::E0283,
255                        true,
256                    )
257                } else {
258                    struct_span_code_err!(
259                        self.dcx(),
260                        span,
261                        E0283,
262                        "type annotations needed: cannot satisfy `{}`",
263                        self.tcx.short_string(predicate, &mut file),
264                    )
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 file);
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_item(*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            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 file);
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                } else {
550                    // If we can't find a generic parameter, just print a generic error
551                    struct_span_code_err!(
552                        self.dcx(),
553                        span,
554                        E0284,
555                        "type annotations needed: cannot satisfy `{predicate}`",
556                    )
557                    .with_span_label(span, format!("cannot satisfy `{predicate}`"))
558                }
559            }
560
561            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
562                if let Err(e) = predicate.error_reported() {
563                    return e;
564                }
565                if let Some(e) = self.tainted_by_errors() {
566                    return e;
567                }
568                let term =
569                    data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
570                if let Some(term) = term {
571                    let err = self.emit_inference_failure_err(
572                        obligation.cause.body_id,
573                        span,
574                        term,
575                        TypeAnnotationNeeded::E0284,
576                        true,
577                    );
578                    err
579                } else {
580                    // If we can't find a generic parameter, just print a generic error
581                    let predicate = self.tcx.short_string(predicate, &mut file);
582                    struct_span_code_err!(
583                        self.dcx(),
584                        span,
585                        E0284,
586                        "type annotations needed: cannot satisfy `{predicate}`",
587                    )
588                    .with_span_label(span, format!("cannot satisfy `{predicate}`"))
589                }
590            }
591
592            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
593                .emit_inference_failure_err(
594                    obligation.cause.body_id,
595                    span,
596                    ct.into(),
597                    TypeAnnotationNeeded::E0284,
598                    true,
599                ),
600            ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
601                if term.is_infer() =>
602            {
603                if let Some(e) = self.tainted_by_errors() {
604                    return e;
605                }
606                let alias = self.tcx.short_string(alias, &mut file);
607                struct_span_code_err!(
608                    self.dcx(),
609                    span,
610                    E0284,
611                    "type annotations needed: cannot normalize `{alias}`",
612                )
613                .with_span_label(span, format!("cannot normalize `{alias}`"))
614            }
615            ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
616                if let Some(e) = self.tainted_by_errors() {
617                    return e;
618                }
619
620                let mut err;
621
622                if self.tcx.features().staged_api() {
623                    err = self.dcx().struct_span_err(
624                        span,
625                        format!("unstable feature `{sym}` is used without being enabled."),
626                    );
627
628                    err.help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"));
629                } else {
630                    err = feature_err_unstable_feature_bound(
631                        &self.tcx.sess,
632                        sym,
633                        span,
634                        format!("use of unstable library feature `{sym}`"),
635                    );
636                }
637                err
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 file);
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            }
653        };
654        *err.long_ty_path() = file;
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}