Skip to main content

rustc_trait_selection/error_reporting/traits/
mod.rs

1pub mod ambiguity;
2pub mod call_kind;
3pub mod fulfillment_errors;
4pub mod on_unimplemented;
5mod overflow;
6pub mod suggestions;
7
8use std::{fmt, iter};
9
10use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
11use rustc_data_structures::stack::ensure_sufficient_stack;
12use rustc_data_structures::unord::UnordSet;
13use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
14use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
15use rustc_hir::intravisit::Visitor;
16use rustc_hir::{self as hir, AmbigArg};
17use rustc_infer::traits::solve::Goal;
18use rustc_infer::traits::{
19    DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode,
20    PredicateObligation, SelectionError,
21};
22use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
23use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
24use rustc_session::cstore::{ExternCrate, ExternCrateSource};
25use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span};
26use tracing::{info, instrument};
27
28pub use self::overflow::*;
29use crate::error_reporting::TypeErrCtxt;
30use crate::traits::{FulfillmentError, FulfillmentErrorCode};
31
32// When outputting impl candidates, prefer showing those that are more similar.
33//
34// We also compare candidates after skipping lifetimes, which has a lower
35// priority than exact matches.
36#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CandidateSimilarity {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            CandidateSimilarity::Exact { ignoring_lifetimes: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Exact",
                    "ignoring_lifetimes", &__self_0),
            CandidateSimilarity::Fuzzy { ignoring_lifetimes: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Fuzzy",
                    "ignoring_lifetimes", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for CandidateSimilarity { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CandidateSimilarity {
    #[inline]
    fn clone(&self) -> CandidateSimilarity {
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for CandidateSimilarity {
    #[inline]
    fn eq(&self, other: &CandidateSimilarity) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (CandidateSimilarity::Exact { ignoring_lifetimes: __self_0 },
                    CandidateSimilarity::Exact { ignoring_lifetimes: __arg1_0 })
                    => __self_0 == __arg1_0,
                (CandidateSimilarity::Fuzzy { ignoring_lifetimes: __self_0 },
                    CandidateSimilarity::Fuzzy { ignoring_lifetimes: __arg1_0 })
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for CandidateSimilarity {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for CandidateSimilarity {
    #[inline]
    fn partial_cmp(&self, other: &CandidateSimilarity)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match (self, other) {
            (CandidateSimilarity::Exact { ignoring_lifetimes: __self_0 },
                CandidateSimilarity::Exact { ignoring_lifetimes: __arg1_0 })
                => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            (CandidateSimilarity::Fuzzy { ignoring_lifetimes: __self_0 },
                CandidateSimilarity::Fuzzy { ignoring_lifetimes: __arg1_0 })
                => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            _ =>
                ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
                    &__arg1_discr),
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for CandidateSimilarity {
    #[inline]
    fn cmp(&self, other: &CandidateSimilarity) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
            ::core::cmp::Ordering::Equal =>
                match (self, other) {
                    (CandidateSimilarity::Exact { ignoring_lifetimes: __self_0
                        }, CandidateSimilarity::Exact { ignoring_lifetimes: __arg1_0
                        }) => ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    (CandidateSimilarity::Fuzzy { ignoring_lifetimes: __self_0
                        }, CandidateSimilarity::Fuzzy { ignoring_lifetimes: __arg1_0
                        }) => ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    _ => unsafe { ::core::intrinsics::unreachable() }
                },
            cmp => cmp,
        }
    }
}Ord)]
37pub enum CandidateSimilarity {
38    Exact { ignoring_lifetimes: bool },
39    Fuzzy { ignoring_lifetimes: bool },
40}
41
42#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ImplCandidate<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "ImplCandidate",
            "trait_ref", &self.trait_ref, "similarity", &self.similarity,
            "impl_def_id", &&self.impl_def_id)
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for ImplCandidate<'tcx> {
    #[inline]
    fn clone(&self) -> ImplCandidate<'tcx> {
        let _: ::core::clone::AssertParamIsClone<ty::TraitRef<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<CandidateSimilarity>;
        let _: ::core::clone::AssertParamIsClone<DefId>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ImplCandidate<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for ImplCandidate<'tcx> {
    #[inline]
    fn eq(&self, other: &ImplCandidate<'tcx>) -> bool {
        self.trait_ref == other.trait_ref &&
                self.similarity == other.similarity &&
            self.impl_def_id == other.impl_def_id
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for ImplCandidate<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::TraitRef<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<CandidateSimilarity>;
        let _: ::core::cmp::AssertParamIsEq<DefId>;
    }
}Eq)]
43pub struct ImplCandidate<'tcx> {
44    pub trait_ref: ty::TraitRef<'tcx>,
45    pub similarity: CandidateSimilarity,
46    impl_def_id: DefId,
47}
48
49enum GetSafeTransmuteErrorAndReason {
50    Silent,
51    Default,
52    Error { err_msg: String, safe_transmute_explanation: Option<String> },
53}
54
55/// Crude way of getting back an `Expr` from a `Span`.
56pub struct FindExprBySpan<'hir> {
57    pub span: Span,
58    pub result: Option<&'hir hir::Expr<'hir>>,
59    pub ty_result: Option<&'hir hir::Ty<'hir>>,
60    pub include_closures: bool,
61    pub tcx: TyCtxt<'hir>,
62}
63
64impl<'hir> FindExprBySpan<'hir> {
65    pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self {
66        Self { span, result: None, ty_result: None, tcx, include_closures: false }
67    }
68}
69
70impl<'v> Visitor<'v> for FindExprBySpan<'v> {
71    type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
72
73    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
74        self.tcx
75    }
76
77    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
78        ensure_sufficient_stack(|| {
79            if self.span == ex.span {
80                self.result = Some(ex);
81            } else {
82                if let hir::ExprKind::Closure(..) = ex.kind
83                    && self.include_closures
84                    && let closure_header_sp = self.span.with_hi(ex.span.hi())
85                    && closure_header_sp == ex.span
86                {
87                    self.result = Some(ex);
88                }
89                hir::intravisit::walk_expr(self, ex);
90            }
91        });
92    }
93
94    fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
95        if self.span == ty.span {
96            self.ty_result = Some(ty.as_unambig_ty());
97        } else {
98            hir::intravisit::walk_ty(self, ty);
99        }
100    }
101}
102
103/// Summarizes information
104#[derive(#[automatically_derived]
impl ::core::clone::Clone for ArgKind {
    #[inline]
    fn clone(&self) -> ArgKind {
        match self {
            ArgKind::Arg(__self_0, __self_1) =>
                ArgKind::Arg(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1)),
            ArgKind::Tuple(__self_0, __self_1) =>
                ArgKind::Tuple(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1)),
        }
    }
}Clone)]
105pub enum ArgKind {
106    /// An argument of non-tuple type. Parameters are (name, ty)
107    Arg(String, String),
108
109    /// An argument of tuple type. For a "found" argument, the span is
110    /// the location in the source of the pattern. For an "expected"
111    /// argument, it will be None. The vector is a list of (name, ty)
112    /// strings for the components of the tuple.
113    Tuple(Option<Span>, Vec<(String, String)>),
114}
115
116impl ArgKind {
117    fn empty() -> ArgKind {
118        ArgKind::Arg("_".to_owned(), "_".to_owned())
119    }
120
121    /// Creates an `ArgKind` from the expected type of an
122    /// argument. It has no name (`_`) and an optional source span.
123    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
124        match t.kind() {
125            ty::Tuple(tys) => ArgKind::Tuple(
126                span,
127                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
128            ),
129            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
130        }
131    }
132}
133
134#[derive(#[automatically_derived]
impl ::core::marker::Copy for DefIdOrName { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DefIdOrName {
    #[inline]
    fn clone(&self) -> DefIdOrName {
        let _: ::core::clone::AssertParamIsClone<DefId>;
        let _: ::core::clone::AssertParamIsClone<&'static str>;
        *self
    }
}Clone)]
135pub enum DefIdOrName {
136    DefId(DefId),
137    Name(&'static str),
138}
139
140impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
141    pub fn report_fulfillment_errors(
142        &self,
143        mut errors: Vec<FulfillmentError<'tcx>>,
144    ) -> ErrorGuaranteed {
145        #[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ErrorDescriptor<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "ErrorDescriptor", "goal", &self.goal, "index", &&self.index)
    }
}Debug)]
146        struct ErrorDescriptor<'tcx> {
147            goal: Goal<'tcx, ty::Predicate<'tcx>>,
148            index: Option<usize>, // None if this is an old error
149        }
150
151        let mut error_map: FxIndexMap<_, Vec<_>> = self
152            .reported_trait_errors
153            .borrow()
154            .iter()
155            .map(|(&span, goals)| {
156                (span, goals.0.iter().map(|&goal| ErrorDescriptor { goal, index: None }).collect())
157            })
158            .collect();
159
160        // Ensure `T: Sized`, `T: MetaSized`, `T: PointeeSized` and `T: WF` obligations come last,
161        // and `Subtype` obligations from `FormatLiteral` desugarings come first.
162        // This lets us display diagnostics with more relevant type information and hide redundant
163        // E0282 errors.
164        #[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErrorSortKey {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ErrorSortKey::SubtypeFormat(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "SubtypeFormat", __self_0, &__self_1),
            ErrorSortKey::OtherKind =>
                ::core::fmt::Formatter::write_str(f, "OtherKind"),
            ErrorSortKey::SizedTrait =>
                ::core::fmt::Formatter::write_str(f, "SizedTrait"),
            ErrorSortKey::MetaSizedTrait =>
                ::core::fmt::Formatter::write_str(f, "MetaSizedTrait"),
            ErrorSortKey::PointeeSizedTrait =>
                ::core::fmt::Formatter::write_str(f, "PointeeSizedTrait"),
            ErrorSortKey::Coerce =>
                ::core::fmt::Formatter::write_str(f, "Coerce"),
            ErrorSortKey::WellFormed =>
                ::core::fmt::Formatter::write_str(f, "WellFormed"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for ErrorSortKey {
    #[inline]
    fn eq(&self, other: &ErrorSortKey) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (ErrorSortKey::SubtypeFormat(__self_0, __self_1),
                    ErrorSortKey::SubtypeFormat(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ErrorSortKey {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for ErrorSortKey {
    #[inline]
    fn partial_cmp(&self, other: &ErrorSortKey)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match (self, other) {
            (ErrorSortKey::SubtypeFormat(__self_0, __self_1),
                ErrorSortKey::SubtypeFormat(__arg1_0, __arg1_1)) =>
                match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
                    {
                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
                        => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
                    cmp => cmp,
                },
            _ =>
                ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
                    &__arg1_discr),
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for ErrorSortKey {
    #[inline]
    fn cmp(&self, other: &ErrorSortKey) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
            ::core::cmp::Ordering::Equal =>
                match (self, other) {
                    (ErrorSortKey::SubtypeFormat(__self_0, __self_1),
                        ErrorSortKey::SubtypeFormat(__arg1_0, __arg1_1)) =>
                        match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
                            ::core::cmp::Ordering::Equal =>
                                ::core::cmp::Ord::cmp(__self_1, __arg1_1),
                            cmp => cmp,
                        },
                    _ => ::core::cmp::Ordering::Equal,
                },
            cmp => cmp,
        }
    }
}Ord)]
165        enum ErrorSortKey {
166            SubtypeFormat(usize, usize),
167            OtherKind,
168            SizedTrait,
169            MetaSizedTrait,
170            PointeeSizedTrait,
171            Coerce,
172            WellFormed,
173        }
174        errors.sort_by_key(|e| {
175            let maybe_sizedness_did = match e.obligation.predicate.kind().skip_binder() {
176                ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => Some(pred.def_id()),
177                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => Some(pred.def_id()),
178                _ => None,
179            };
180
181            match e.obligation.predicate.kind().skip_binder() {
182                ty::PredicateKind::Subtype(_)
183                    if #[allow(non_exhaustive_omitted_patterns)] match e.obligation.cause.span.desugaring_kind()
    {
    Some(DesugaringKind::FormatLiteral { .. }) => true,
    _ => false,
}matches!(
184                        e.obligation.cause.span.desugaring_kind(),
185                        Some(DesugaringKind::FormatLiteral { .. })
186                    ) =>
187                {
188                    let (_, row, col, ..) =
189                        self.tcx.sess.source_map().span_to_location_info(e.obligation.cause.span);
190                    ErrorSortKey::SubtypeFormat(row, col)
191                }
192                _ if maybe_sizedness_did == self.tcx.lang_items().sized_trait() => {
193                    ErrorSortKey::SizedTrait
194                }
195                _ if maybe_sizedness_did == self.tcx.lang_items().meta_sized_trait() => {
196                    ErrorSortKey::MetaSizedTrait
197                }
198                _ if maybe_sizedness_did == self.tcx.lang_items().pointee_sized_trait() => {
199                    ErrorSortKey::PointeeSizedTrait
200                }
201                ty::PredicateKind::Coerce(_) => ErrorSortKey::Coerce,
202                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {
203                    ErrorSortKey::WellFormed
204                }
205                _ => ErrorSortKey::OtherKind,
206            }
207        });
208
209        for (index, error) in errors.iter().enumerate() {
210            // We want to ignore desugarings here: spans are equivalent even
211            // if one is the result of a desugaring and the other is not.
212            let mut span = error.obligation.cause.span;
213            let expn_data = span.ctxt().outer_expn_data();
214            if let ExpnKind::Desugaring(_) = expn_data.kind {
215                span = expn_data.call_site;
216            }
217
218            error_map
219                .entry(span)
220                .or_default()
221                .push(ErrorDescriptor { goal: error.obligation.as_goal(), index: Some(index) });
222        }
223
224        // We do this in 2 passes because we want to display errors in order, though
225        // maybe it *is* better to sort errors by span or something.
226        let mut is_suppressed = ::alloc::vec::from_elem(false, errors.len())vec![false; errors.len()];
227        for (_, error_set) in error_map.iter() {
228            // We want to suppress "duplicate" errors with the same span.
229            for error in error_set {
230                if let Some(index) = error.index {
231                    // Suppress errors that are either:
232                    // 1) strictly implied by another error.
233                    // 2) implied by an error with a smaller index.
234                    for error2 in error_set {
235                        if error2.index.is_some_and(|index2| is_suppressed[index2]) {
236                            // Avoid errors being suppressed by already-suppressed
237                            // errors, to prevent all errors from being suppressed
238                            // at once.
239                            continue;
240                        }
241
242                        if self.error_implies(error2.goal, error.goal)
243                            && !(error2.index >= error.index
244                                && self.error_implies(error.goal, error2.goal))
245                        {
246                            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs:246",
                        "rustc_trait_selection::error_reporting::traits",
                        ::tracing::Level::INFO,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(246u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::INFO <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("skipping {0:?} (implied by {1:?})",
                                                    error, error2) as &dyn Value))])
            });
    } else { ; }
};info!("skipping {:?} (implied by {:?})", error, error2);
247                            is_suppressed[index] = true;
248                            break;
249                        }
250                    }
251                }
252            }
253        }
254
255        let mut reported = None;
256        for from_expansion in [false, true] {
257            for (error, suppressed) in iter::zip(&errors, &is_suppressed) {
258                if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion {
259                    if !error.references_error() {
260                        let guar = self.report_fulfillment_error(error);
261                        self.infcx.set_tainted_by_errors(guar);
262                        reported = Some(guar);
263                        // We want to ignore desugarings here: spans are equivalent even
264                        // if one is the result of a desugaring and the other is not.
265                        let mut span = error.obligation.cause.span;
266                        let expn_data = span.ctxt().outer_expn_data();
267                        if let ExpnKind::Desugaring(_) = expn_data.kind {
268                            span = expn_data.call_site;
269                        }
270                        self.reported_trait_errors
271                            .borrow_mut()
272                            .entry(span)
273                            .or_insert_with(|| (::alloc::vec::Vec::new()vec![], guar))
274                            .0
275                            .push(error.obligation.as_goal());
276                    }
277                    if let Some(guar) = self.dcx().has_errors() {
278                        self.infcx.set_tainted_by_errors(guar);
279                    }
280                }
281            }
282        }
283
284        // It could be that we don't report an error because we have seen an `ErrorReported` from
285        // another source. We should probably be able to fix most of these, but some are delayed
286        // bugs that get a proper error after this function.
287        reported.unwrap_or_else(|| self.dcx().delayed_bug("failed to report fulfillment errors"))
288    }
289
290    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("report_fulfillment_error",
                                    "rustc_trait_selection::error_reporting::traits",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs"),
                                    ::tracing_core::__macro_support::Option::Some(290u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits"),
                                    ::tracing_core::field::FieldSet::new(&["error"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&error)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: ErrorGuaranteed = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let mut error =
                FulfillmentError {
                    obligation: error.obligation.clone(),
                    code: error.code.clone(),
                    root_obligation: error.root_obligation.clone(),
                };
            if #[allow(non_exhaustive_omitted_patterns)] match error.code {
                        FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented)
                            | FulfillmentErrorCode::Project(_) => true,
                        _ => false,
                    } && self.apply_do_not_recommend(&mut error.obligation) {
                error.code =
                    FulfillmentErrorCode::Select(SelectionError::Unimplemented);
            }
            match error.code {
                FulfillmentErrorCode::Select(ref selection_error) =>
                    self.report_selection_error(error.obligation.clone(),
                        &error.root_obligation, selection_error),
                FulfillmentErrorCode::Project(ref e) => {
                    self.report_projection_error(&error.obligation, e)
                }
                FulfillmentErrorCode::Ambiguity { overflow: None } => {
                    self.maybe_report_ambiguity(&error.obligation)
                }
                FulfillmentErrorCode::Ambiguity {
                    overflow: Some(suggest_increasing_limit) } => {
                    self.report_overflow_no_abort(error.obligation.clone(),
                        suggest_increasing_limit)
                }
                FulfillmentErrorCode::Subtype(ref expected_found, ref err) =>
                    self.report_mismatched_types(&error.obligation.cause,
                            error.obligation.param_env, expected_found.expected,
                            expected_found.found, *err).emit(),
                FulfillmentErrorCode::ConstEquate(ref expected_found, ref err)
                    => {
                    let mut diag =
                        self.report_mismatched_consts(&error.obligation.cause,
                            error.obligation.param_env, expected_found.expected,
                            expected_found.found, *err);
                    let code =
                        error.obligation.cause.code().peel_derives().peel_match_impls();
                    if let ObligationCauseCode::WhereClause(..) |
                            ObligationCauseCode::WhereClauseInExpr(..) = code {
                        self.note_obligation_cause_code(error.obligation.cause.body_id,
                            &mut diag, error.obligation.predicate,
                            error.obligation.param_env, code,
                            &mut ::alloc::vec::Vec::new(), &mut Default::default());
                    }
                    diag.emit()
                }
                FulfillmentErrorCode::Cycle(ref cycle) =>
                    self.report_overflow_obligation_cycle(cycle),
            }
        }
    }
}#[instrument(skip(self), level = "debug")]
291    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed {
292        let mut error = FulfillmentError {
293            obligation: error.obligation.clone(),
294            code: error.code.clone(),
295            root_obligation: error.root_obligation.clone(),
296        };
297        if matches!(
298            error.code,
299            FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented)
300                | FulfillmentErrorCode::Project(_)
301        ) && self.apply_do_not_recommend(&mut error.obligation)
302        {
303            error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented);
304        }
305
306        match error.code {
307            FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error(
308                error.obligation.clone(),
309                &error.root_obligation,
310                selection_error,
311            ),
312            FulfillmentErrorCode::Project(ref e) => {
313                self.report_projection_error(&error.obligation, e)
314            }
315            FulfillmentErrorCode::Ambiguity { overflow: None } => {
316                self.maybe_report_ambiguity(&error.obligation)
317            }
318            FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) } => {
319                self.report_overflow_no_abort(error.obligation.clone(), suggest_increasing_limit)
320            }
321            FulfillmentErrorCode::Subtype(ref expected_found, ref err) => self
322                .report_mismatched_types(
323                    &error.obligation.cause,
324                    error.obligation.param_env,
325                    expected_found.expected,
326                    expected_found.found,
327                    *err,
328                )
329                .emit(),
330            FulfillmentErrorCode::ConstEquate(ref expected_found, ref err) => {
331                let mut diag = self.report_mismatched_consts(
332                    &error.obligation.cause,
333                    error.obligation.param_env,
334                    expected_found.expected,
335                    expected_found.found,
336                    *err,
337                );
338                let code = error.obligation.cause.code().peel_derives().peel_match_impls();
339                if let ObligationCauseCode::WhereClause(..)
340                | ObligationCauseCode::WhereClauseInExpr(..) = code
341                {
342                    self.note_obligation_cause_code(
343                        error.obligation.cause.body_id,
344                        &mut diag,
345                        error.obligation.predicate,
346                        error.obligation.param_env,
347                        code,
348                        &mut vec![],
349                        &mut Default::default(),
350                    );
351                }
352                diag.emit()
353            }
354            FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle),
355        }
356    }
357
358    /// If the crates of `expected_def_id` and `trait_def_id` are imported as extern crate
359    /// under the same name (`extern crate foo as a` and `extern crate bar as a`) returns true,
360    /// otherwise returns false.
361    fn extern_crates_with_the_same_name(
362        &self,
363        expected_def_id: DefId,
364        trait_def_id: DefId,
365    ) -> bool {
366        if expected_def_id.is_local() || trait_def_id.is_local() {
367            return false;
368        }
369        // We only compare direct dependencies of the current crate, so it avoids unnecessary
370        // processing and excludes indirect dependencies, like `std` or `core`. In such a case
371        // both would be imported under the same name `std`.
372        match (
373            self.tcx.extern_crate(expected_def_id.krate),
374            self.tcx.extern_crate(trait_def_id.krate),
375        ) {
376            (
377                Some(&ExternCrate {
378                    src: ExternCrateSource::Extern(expected_def_id),
379                    dependency_of: LOCAL_CRATE,
380                    ..
381                }),
382                Some(&ExternCrate {
383                    src: ExternCrateSource::Extern(trait_def_id),
384                    dependency_of: LOCAL_CRATE,
385                    ..
386                }),
387            ) => self.tcx.item_name(expected_def_id) == self.tcx.item_name(trait_def_id),
388            _ => false,
389        }
390    }
391
392    pub fn check_same_definition_different_crate<F>(
393        &self,
394        err: &mut Diag<'_>,
395        expected_did: DefId,
396        found_dids: impl Iterator<Item = DefId>,
397        get_impls: F,
398        ty: &str,
399    ) -> bool
400    where
401        F: Fn(DefId) -> Vec<Span>,
402    {
403        let krate = self.tcx.crate_name(expected_did.krate);
404        let name = self.tcx.item_name(expected_did);
405        let definitions_with_same_path: UnordSet<_> = found_dids
406            .filter(|&def_id| {
407                def_id.krate != expected_did.krate
408                    && (self.extern_crates_with_the_same_name(expected_did, def_id)
409                        || self.tcx.crate_name(def_id.krate) == krate)
410                    && self.tcx.item_name(def_id) == name
411            })
412            .map(|def_id| (self.tcx.def_path_str(def_id), def_id))
413            .collect();
414
415        let definitions_with_same_path =
416            definitions_with_same_path.into_items().into_sorted_stable_ord_by_key(|(p, _)| p);
417        let mut suggested = false;
418        let mut trait_is_impl = false;
419
420        if !definitions_with_same_path.is_empty() {
421            let mut span: MultiSpan = self.tcx.def_span(expected_did).into();
422            span.push_span_label(
423                self.tcx.def_span(expected_did),
424                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this is the expected {0}", ty))
    })format!("this is the expected {ty}"),
425            );
426            suggested = true;
427            for (_, definition_with_same_path) in &definitions_with_same_path {
428                let definitions_impls = get_impls(*definition_with_same_path);
429                if definitions_impls.is_empty() {
430                    continue;
431                }
432
433                for candidate_span in definitions_impls {
434                    span.push_span_label(candidate_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this is the found {0}", ty))
    })format!("this is the found {ty}"));
435                    trait_is_impl = true;
436                }
437            }
438            if !trait_is_impl {
439                for (_, def_id) in definitions_with_same_path {
440                    span.push_span_label(
441                        self.tcx.def_span(def_id),
442                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this is the {0} that was imported",
                ty))
    })format!("this is the {ty} that was imported"),
443                    );
444                }
445            }
446            self.note_two_crate_versions(expected_did.krate, span, err);
447            err.help("you can use `cargo tree` to explore your dependency tree");
448        }
449        suggested
450    }
451}
452
453/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
454/// string.
455pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
456    use std::fmt::Write;
457
458    let trait_ref = tcx.impl_opt_trait_ref(impl_def_id)?.instantiate_identity().skip_norm_wip();
459    let mut w = "impl".to_owned();
460
461    #[derive(#[automatically_derived]
impl ::core::fmt::Debug for SizednessFound {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "SizednessFound", "sized", &self.sized, "meta_sized",
            &&self.meta_sized)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for SizednessFound {
    #[inline]
    fn default() -> SizednessFound {
        SizednessFound {
            sized: ::core::default::Default::default(),
            meta_sized: ::core::default::Default::default(),
        }
    }
}Default)]
462    struct SizednessFound {
463        sized: bool,
464        meta_sized: bool,
465    }
466
467    let mut types_with_sizedness_bounds = FxIndexMap::<_, SizednessFound>::default();
468
469    let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id);
470
471    let arg_names = args.iter().map(|k| k.to_string()).filter(|k| k != "'_").collect::<Vec<_>>();
472    if !arg_names.is_empty() {
473        w.push('<');
474        w.push_str(&arg_names.join(", "));
475        w.push('>');
476
477        for ty in args.types() {
478            // `PointeeSized` params might have no predicates.
479            types_with_sizedness_bounds.insert(ty, SizednessFound::default());
480        }
481    }
482
483    w.write_fmt(format_args!(" {0}{1} for {2}",
        tcx.impl_polarity(impl_def_id).as_str(),
        trait_ref.print_only_trait_path(),
        tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip()))write!(
484        w,
485        " {}{} for {}",
486        tcx.impl_polarity(impl_def_id).as_str(),
487        trait_ref.print_only_trait_path(),
488        tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip()
489    )
490    .unwrap();
491
492    let predicates = tcx.predicates_of(impl_def_id).predicates;
493    let mut pretty_predicates = Vec::with_capacity(predicates.len());
494
495    let sized_trait = tcx.lang_items().sized_trait();
496    let meta_sized_trait = tcx.lang_items().meta_sized_trait();
497
498    for (p, _) in predicates {
499        // Accumulate the sizedness bounds for each self ty.
500        if let Some(trait_clause) = p.as_trait_clause() {
501            let self_ty = trait_clause.self_ty().skip_binder();
502            let sizedness_of = types_with_sizedness_bounds.entry(self_ty).or_default();
503            if Some(trait_clause.def_id()) == sized_trait {
504                sizedness_of.sized = true;
505                continue;
506            } else if Some(trait_clause.def_id()) == meta_sized_trait {
507                sizedness_of.meta_sized = true;
508                continue;
509            }
510        }
511
512        pretty_predicates.push(p.to_string());
513    }
514
515    for (ty, sizedness) in types_with_sizedness_bounds {
516        if !tcx.features().sized_hierarchy() {
517            if sizedness.sized {
518                // Maybe a default bound, don't write anything.
519            } else {
520                pretty_predicates.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: ?Sized", ty))
    })format!("{ty}: ?Sized"));
521            }
522        } else {
523            if sizedness.sized {
524                // Maybe a default bound, don't write anything.
525                pretty_predicates.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: Sized", ty))
    })format!("{ty}: Sized"));
526            } else if sizedness.meta_sized {
527                pretty_predicates.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: MetaSized", ty))
    })format!("{ty}: MetaSized"));
528            } else {
529                pretty_predicates.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: PointeeSized", ty))
    })format!("{ty}: PointeeSized"));
530            }
531        }
532    }
533
534    if !pretty_predicates.is_empty() {
535        w.write_fmt(format_args!("\n  where {0}", pretty_predicates.join(", ")))write!(w, "\n  where {}", pretty_predicates.join(", ")).unwrap();
536    }
537
538    w.push(';');
539    Some(w)
540}
541
542impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
543    pub fn report_extra_impl_obligation(
544        &self,
545        error_span: Span,
546        impl_item_def_id: LocalDefId,
547        trait_item_def_id: DefId,
548        requirement: &dyn fmt::Display,
549    ) -> Diag<'a> {
550        let mut err = {
    self.dcx().struct_span_err(error_span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("impl has stricter requirements than trait"))
                })).with_code(E0276)
}struct_span_code_err!(
551            self.dcx(),
552            error_span,
553            E0276,
554            "impl has stricter requirements than trait"
555        );
556
557        if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) {
558            if let Some(span) = self.tcx.hir_span_if_local(trait_item_def_id) {
559                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
560                err.span_label(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("definition of `{0}` from trait",
                item_name))
    })format!("definition of `{item_name}` from trait"));
561            }
562        }
563
564        err.span_label(error_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("impl has extra requirement {0}",
                requirement))
    })format!("impl has extra requirement {requirement}"));
565
566        err
567    }
568}
569
570pub fn report_dyn_incompatibility<'tcx>(
571    tcx: TyCtxt<'tcx>,
572    span: Span,
573    hir_id: Option<hir::HirId>,
574    trait_def_id: DefId,
575    violations: &[DynCompatibilityViolation],
576) -> Diag<'tcx> {
577    let trait_str = tcx.def_path_str(trait_def_id);
578    let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node {
579        hir::Node::Item(item) => match item.kind {
580            hir::ItemKind::Trait(_, _, _, _, ident, ..)
581            | hir::ItemKind::TraitAlias(_, ident, _, _) => Some(ident.span),
582            _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
583        },
584        _ => None,
585    });
586
587    let mut err = {
    tcx.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("the {0} `{1}` is not dyn compatible",
                            tcx.def_descr(trait_def_id), trait_str))
                })).with_code(E0038)
}struct_span_code_err!(
588        tcx.dcx(),
589        span,
590        E0038,
591        "the {} `{}` is not dyn compatible",
592        tcx.def_descr(trait_def_id),
593        trait_str
594    );
595    err.span_label(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is not dyn compatible",
                trait_str))
    })format!("`{trait_str}` is not dyn compatible"));
596
597    attempt_dyn_to_impl_suggestion(tcx, hir_id, &mut err);
598
599    let mut reported_violations = FxIndexSet::default();
600    let mut multi_span = ::alloc::vec::Vec::new()vec![];
601    let mut messages = ::alloc::vec::Vec::new()vec![];
602    for violation in violations {
603        if let DynCompatibilityViolation::SizedSelf(sp) = &violation
604            && !sp.is_empty()
605        {
606            // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
607            // with a `Span`.
608            reported_violations.insert(DynCompatibilityViolation::SizedSelf(::alloc::vec::Vec::new()vec![].into()));
609        }
610        if reported_violations.insert(violation.clone()) {
611            let spans = violation.spans();
612            let msg = if trait_span.is_none() || spans.is_empty() {
613                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the trait is not dyn compatible because {0}",
                violation.error_msg()))
    })format!("the trait is not dyn compatible because {}", violation.error_msg())
614            } else {
615                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("...because {0}",
                violation.error_msg()))
    })format!("...because {}", violation.error_msg())
616            };
617            if spans.is_empty() {
618                err.note(msg);
619            } else {
620                for span in spans {
621                    multi_span.push(span);
622                    messages.push(msg.clone());
623                }
624            }
625        }
626    }
627    let has_multi_span = !multi_span.is_empty();
628    let mut note_span = MultiSpan::from_spans(multi_span.clone());
629    if let (Some(trait_span), true) = (trait_span, has_multi_span) {
630        note_span.push_span_label(trait_span, "this trait is not dyn compatible...");
631    }
632    for (span, msg) in iter::zip(multi_span, messages) {
633        note_span.push_span_label(span, msg);
634    }
635    err.span_note(
636        note_span,
637        "for a trait to be dyn compatible it needs to allow building a vtable\n\
638        for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>",
639    );
640
641    // Only provide the help if its a local trait, otherwise it's not actionable.
642    if trait_span.is_some() {
643        let mut potential_solutions: Vec<_> =
644            reported_violations.into_iter().map(|violation| violation.solution()).collect();
645        potential_solutions.sort();
646        // Allows us to skip suggesting that the same item should be moved to another trait multiple times.
647        potential_solutions.dedup();
648        for solution in potential_solutions {
649            solution.add_to(&mut err);
650        }
651    }
652
653    attempt_dyn_to_enum_suggestion(tcx, trait_def_id, &*trait_str, &mut err);
654
655    err
656}
657
658/// Attempt to suggest converting the `dyn Trait` argument to an enumeration
659/// over the types that implement `Trait`.
660fn attempt_dyn_to_enum_suggestion(
661    tcx: TyCtxt<'_>,
662    trait_def_id: DefId,
663    trait_str: &str,
664    err: &mut Diag<'_>,
665) {
666    let impls_of = tcx.trait_impls_of(trait_def_id);
667
668    if !impls_of.blanket_impls().is_empty() {
669        return;
670    }
671
672    let concrete_impls: Option<Vec<Ty<'_>>> = impls_of
673        .non_blanket_impls()
674        .values()
675        .flatten()
676        .map(|impl_id| {
677            // Don't suggest conversion to enum if the impl types have type parameters.
678            // It's unlikely the user wants to define a generic enum.
679            let Some(impl_type) = tcx.type_of(*impl_id).no_bound_vars() else { return None };
680
681            // Obviously unsized impl types won't be usable in an enum.
682            // Note: this doesn't use `Ty::has_trivial_sizedness` because that function
683            // defaults to assuming that things are *not* sized, whereas we want to
684            // fall back to assuming that things may be sized.
685            match impl_type.kind() {
686                ty::Str | ty::Slice(_) | ty::Dynamic(_, _) => {
687                    return None;
688                }
689                _ => {}
690            }
691            Some(impl_type)
692        })
693        .collect();
694    let Some(concrete_impls) = concrete_impls else { return };
695
696    const MAX_IMPLS_TO_SUGGEST_CONVERTING_TO_ENUM: usize = 9;
697    if concrete_impls.is_empty() || concrete_impls.len() > MAX_IMPLS_TO_SUGGEST_CONVERTING_TO_ENUM {
698        return;
699    }
700
701    let externally_visible = if let Some(def_id) = trait_def_id.as_local() {
702        // We may be executing this during typeck, which would result in cycle
703        // if we used effective_visibilities query, which looks into opaque types
704        // (and therefore calls typeck).
705        tcx.resolutions(()).effective_visibilities.is_exported(def_id)
706    } else {
707        false
708    };
709
710    if let [only_impl] = &concrete_impls[..] {
711        let within = if externally_visible { " within this crate" } else { "" };
712        err.help({
    let _guard = NoTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("only type `{0}` implements `{1}`{2}; consider using it directly instead.",
                    only_impl, trait_str, within))
        })
}with_no_trimmed_paths!(format!(
713            "only type `{only_impl}` implements `{trait_str}`{within}; \
714            consider using it directly instead."
715        )));
716    } else {
717        let types = concrete_impls
718            .iter()
719            .map(|t| {
    let _guard = NoTrimmedGuard::new();
    ::alloc::__export::must_use({
            ::alloc::fmt::format(format_args!("  {0}", t))
        })
}with_no_trimmed_paths!(format!("  {}", t)))
720            .collect::<Vec<String>>()
721            .join("\n");
722
723        err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the following types implement `{0}`:\n{1}\nconsider defining an enum where each variant holds one of these types,\nimplementing `{0}` for this new enum and using it instead",
                trait_str, types))
    })format!(
724            "the following types implement `{trait_str}`:\n\
725             {types}\n\
726             consider defining an enum where each variant holds one of these types,\n\
727             implementing `{trait_str}` for this new enum and using it instead",
728        ));
729    }
730
731    if externally_visible {
732        err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` may be implemented in other crates; if you want to support your users passing their own types here, you can\'t refer to a specific type",
                trait_str))
    })format!(
733            "`{trait_str}` may be implemented in other crates; if you want to support your users \
734             passing their own types here, you can't refer to a specific type",
735        ));
736    }
737}
738
739/// Attempt to suggest that a `dyn Trait` argument or return type be converted
740/// to use `impl Trait`.
741fn attempt_dyn_to_impl_suggestion(tcx: TyCtxt<'_>, hir_id: Option<hir::HirId>, err: &mut Diag<'_>) {
742    let Some(hir_id) = hir_id else { return };
743    let hir::Node::Ty(ty) = tcx.hir_node(hir_id) else { return };
744    let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind else { return };
745
746    // Only suggest converting `dyn` to `impl` if we're in a function signature.
747    // This ensures that we don't suggest converting e.g.
748    //   `type Alias = Box<dyn DynIncompatibleTrait>;` to
749    //   `type Alias = Box<impl DynIncompatibleTrait>;`
750    let Some((_id, first_non_type_parent_node)) =
751        tcx.hir_parent_iter(hir_id).find(|(_id, node)| !#[allow(non_exhaustive_omitted_patterns)] match node {
    hir::Node::Ty(_) => true,
    _ => false,
}matches!(node, hir::Node::Ty(_)))
752    else {
753        return;
754    };
755    if first_non_type_parent_node.fn_sig().is_none() {
756        return;
757    }
758
759    err.span_suggestion_verbose(
760        ty.span.until(trait_ref.span),
761        "consider using an opaque type instead",
762        "impl ",
763        Applicability::MaybeIncorrect,
764    );
765}