Skip to main content

rustc_trait_selection/error_reporting/infer/nice_region_error/
placeholder_error.rs

1use std::fmt;
2
3use rustc_data_structures::intern::Interned;
4use rustc_errors::{Applicability, Diag, IntoDiagArg};
5use rustc_hir as hir;
6use rustc_hir::def::Namespace;
7use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
8use rustc_middle::ty::error::ExpectedFound;
9use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
10use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt};
11use rustc_span::bug;
12use rustc_structures::Limit;
13use tracing::{debug, instrument};
14
15use crate::diagnostics::{
16    ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
17    TraitPlaceholderMismatch, TyOrSig,
18};
19use crate::error_reporting::infer::nice_region_error::NiceRegionError;
20use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace, ValuePairs};
21use crate::traits::{ObligationCause, ObligationCauseCode};
22
23#[derive(#[automatically_derived]
impl<'tcx, T: ::core::marker::Copy> ::core::marker::Copy for
    Highlighted<'tcx, T> {
}Copy, #[automatically_derived]
impl<'tcx, T: ::core::clone::Clone> ::core::clone::Clone for
    Highlighted<'tcx, T> {
    #[inline]
    fn clone(&self) -> Self {
        Highlighted {
            tcx: ::core::clone::Clone::clone(&self.tcx),
            highlight: ::core::clone::Clone::clone(&self.highlight),
            value: ::core::clone::Clone::clone(&self.value),
            ns: ::core::clone::Clone::clone(&self.ns),
        }
    }
}Clone)]
24pub(crate) struct Highlighted<'tcx, T> {
25    pub tcx: TyCtxt<'tcx>,
26    pub highlight: RegionHighlightMode<'tcx>,
27    pub value: T,
28    pub ns: Namespace,
29}
30
31impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
32where
33    T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
34{
35    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
36        rustc_errors::DiagArgValue::Str(self.to_string().into())
37    }
38}
39
40impl<'tcx, T> Highlighted<'tcx, T> {
41    fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
42        Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value), ns: self.ns }
43    }
44}
45
46impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
47where
48    T: for<'a> Print<FmtPrinter<'a, 'tcx>> + Copy,
49{
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        let mut p = ty::print::FmtPrinter::new(self.tcx, self.ns);
52        p.region_highlight_mode = self.highlight;
53
54        self.value.print(&mut p)?;
55        let b = p.into_buffer();
56        if b.len() <= 40 || !self.highlight.keep_regions || self.tcx.sess.opts.verbose {
57            // This is a short enough type that can be safely be printed to the user, or we aren't
58            // showing the type with a particular interest in its lifetimes.
59            f.write_str(&b)?;
60        } else {
61            // We are highlighting lifetimes in the output, we will print out the smallest possible
62            // portion of the type while keeping the lifetimes visible.
63            let mut p = FmtPrinter::new_with_limit(self.tcx, self.ns, Limit(0));
64            p.region_highlight_mode = self.highlight;
65            self.value.print(&mut p).expect("could not print type");
66            let x = p.into_buffer();
67            f.write_str(&x)?;
68        }
69        Ok(())
70    }
71}
72
73impl<'tcx> NiceRegionError<'_, 'tcx> {
74    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
75    /// an anonymous region, emit a descriptive diagnostic error.
76    pub(super) fn try_report_placeholder_conflict(&self) -> Option<Diag<'tcx>> {
77        match &self.error {
78            ///////////////////////////////////////////////////////////////////////////
79            // NB. The ordering of cases in this match is very
80            // sensitive, because we are often matching against
81            // specific cases and then using an `_` to match all
82            // others.
83
84            ///////////////////////////////////////////////////////////////////////////
85            // Check for errors from comparing trait failures -- first
86            // with two placeholders, then with one.
87            Some(RegionResolutionError::SubSupConflict(
88                vid,
89                _,
90                SubregionOrigin::Subtype(TypeTrace { cause, values }),
91                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
92                _,
93                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
94                _,
95            )) => self.try_report_trait_placeholder_mismatch(
96                Some(ty::Region::new_var(self.tcx(), *vid)),
97                cause,
98                Some(*sub_placeholder),
99                Some(*sup_placeholder),
100                values,
101            ),
102
103            Some(RegionResolutionError::SubSupConflict(
104                vid,
105                _,
106                SubregionOrigin::Subtype(TypeTrace { cause, values }),
107                sub_placeholder @ Region(Interned(RePlaceholder(_), _)),
108                _,
109                _,
110                _,
111            )) => self.try_report_trait_placeholder_mismatch(
112                Some(ty::Region::new_var(self.tcx(), *vid)),
113                cause,
114                Some(*sub_placeholder),
115                None,
116                values,
117            ),
118
119            Some(RegionResolutionError::SubSupConflict(
120                vid,
121                _,
122                SubregionOrigin::Subtype(TypeTrace { cause, values }),
123                _,
124                _,
125                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
126                _,
127            )) => self.try_report_trait_placeholder_mismatch(
128                Some(ty::Region::new_var(self.tcx(), *vid)),
129                cause,
130                None,
131                Some(*sup_placeholder),
132                values,
133            ),
134
135            Some(RegionResolutionError::SubSupConflict(
136                vid,
137                _,
138                _,
139                _,
140                SubregionOrigin::Subtype(TypeTrace { cause, values }),
141                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
142                _,
143            )) => self.try_report_trait_placeholder_mismatch(
144                Some(ty::Region::new_var(self.tcx(), *vid)),
145                cause,
146                None,
147                Some(*sup_placeholder),
148                values,
149            ),
150
151            Some(RegionResolutionError::UpperBoundUniverseConflict(
152                vid,
153                _,
154                _,
155                SubregionOrigin::Subtype(TypeTrace { cause, values }),
156                sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
157            )) => self.try_report_trait_placeholder_mismatch(
158                Some(ty::Region::new_var(self.tcx(), *vid)),
159                cause,
160                None,
161                Some(*sup_placeholder),
162                values,
163            ),
164
165            Some(RegionResolutionError::ConcreteFailure(
166                SubregionOrigin::Subtype(TypeTrace { cause, values }),
167                sub_region @ Region(Interned(RePlaceholder(_), _)),
168                sup_region @ Region(Interned(RePlaceholder(_), _)),
169            )) => self.try_report_trait_placeholder_mismatch(
170                None,
171                cause,
172                Some(*sub_region),
173                Some(*sup_region),
174                values,
175            ),
176
177            Some(RegionResolutionError::ConcreteFailure(
178                SubregionOrigin::Subtype(TypeTrace { cause, values }),
179                sub_region @ Region(Interned(RePlaceholder(_), _)),
180                sup_region,
181            )) => self.try_report_trait_placeholder_mismatch(
182                (!sup_region.is_named(self.tcx())).then_some(*sup_region),
183                cause,
184                Some(*sub_region),
185                None,
186                values,
187            ),
188
189            Some(RegionResolutionError::ConcreteFailure(
190                SubregionOrigin::Subtype(TypeTrace { cause, values }),
191                sub_region,
192                sup_region @ Region(Interned(RePlaceholder(_), _)),
193            )) => self.try_report_trait_placeholder_mismatch(
194                (!sub_region.is_named(self.tcx())).then_some(*sub_region),
195                cause,
196                None,
197                Some(*sup_region),
198                values,
199            ),
200
201            _ => None,
202        }
203    }
204
205    fn try_report_trait_placeholder_mismatch(
206        &self,
207        vid: Option<Region<'tcx>>,
208        cause: &ObligationCause<'tcx>,
209        sub_placeholder: Option<Region<'tcx>>,
210        sup_placeholder: Option<Region<'tcx>>,
211        value_pairs: &ValuePairs<'tcx>,
212    ) -> Option<Diag<'tcx>> {
213        let (expected_args, found_args, trait_def_id) = match value_pairs {
214            ValuePairs::TraitRefs(ExpectedFound { expected, found })
215                if expected.def_id == found.def_id =>
216            {
217                // It's possible that the placeholders come from a binder
218                // outside of this value pair. Use `no_bound_vars` as a
219                // simple heuristic for that.
220                (expected.args, found.args, expected.def_id)
221            }
222            _ => return None,
223        };
224
225        Some(self.report_trait_placeholder_mismatch(
226            vid,
227            cause,
228            sub_placeholder,
229            sup_placeholder,
230            trait_def_id,
231            expected_args,
232            found_args,
233        ))
234    }
235
236    // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
237    //   --> /home/nmatsakis/tmp/foo.rs:12:5
238    //    |
239    // 12 |     all::<&'static u32>();
240    //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
241    //    |
242    //    = note: Due to a where-clause on the function `all`,
243    //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
244    //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
245    {}
#[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_trait_placeholder_mismatch",
                                    "rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/8ea38001b9da1d6683ac5ebbc993cac89d3a09df/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
                                    ::tracing_core::__macro_support::Option::Some(245u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("cause")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("cause");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("sub_placeholder")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("sub_placeholder");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("sup_placeholder")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("sup_placeholder");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("trait_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("trait_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected_args")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected_args");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual_args")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual_args");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&vid)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sub_placeholder)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sup_placeholder)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_args)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_args)
                                                            as &dyn ::tracing::field::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: Diag<'tcx> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let span = cause.span;
            let (leading_ellipsis, satisfy_span, where_span, dup_span,
                    def_id) =
                if let ObligationCauseCode::WhereClause(def_id, span) |
                            ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) =
                            *cause.code() && def_id != CRATE_DEF_ID.to_def_id() {
                    (true, Some(span), Some(self.tcx().def_span(def_id)), None,
                        self.tcx().def_path_str(def_id))
                } else { (false, None, None, Some(span), String::new()) };
            let expected_trait_ref =
                self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
                        trait_def_id, expected_args));
            let actual_trait_ref =
                self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
                        trait_def_id, actual_args));
            let mut counter = 0;
            let mut has_sub = None;
            let mut has_sup = None;
            let mut actual_has_vid = None;
            let mut expected_has_vid = None;
            self.tcx().for_each_free_region(&expected_trait_ref,
                |r|
                    {
                        if Some(r) == sub_placeholder && has_sub.is_none() {
                            has_sub = Some(counter);
                            counter += 1;
                        } else if Some(r) == sup_placeholder && has_sup.is_none() {
                            has_sup = Some(counter);
                            counter += 1;
                        }
                        if Some(r) == vid && expected_has_vid.is_none() {
                            expected_has_vid = Some(counter);
                            counter += 1;
                        }
                    });
            self.tcx().for_each_free_region(&actual_trait_ref,
                |r|
                    {
                        if Some(r) == vid && actual_has_vid.is_none() {
                            actual_has_vid = Some(counter);
                            counter += 1;
                        }
                    });
            let actual_self_ty_has_vid =
                self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(),
                    |r| Some(r) == vid);
            let expected_self_ty_has_vid =
                self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(),
                    |r| Some(r) == vid);
            let any_self_ty_has_vid =
                actual_self_ty_has_vid || expected_self_ty_has_vid;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/8ea38001b9da1d6683ac5ebbc993cac89d3a09df/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs:324",
                                    "rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/8ea38001b9da1d6683ac5ebbc993cac89d3a09df/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs"),
                                    ::tracing_core::__macro_support::Option::Some(324u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::nice_region_error::placeholder_error"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual_has_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected_has_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("has_sub")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("has_sub");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("has_sup")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("has_sup");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("actual_self_ty_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("actual_self_ty_has_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("expected_self_ty_has_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("expected_self_ty_has_vid");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_has_vid)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_has_vid)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&has_sub)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&has_sup)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&actual_self_ty_has_vid)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected_self_ty_has_vid)
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            let actual_impl_expl_notes =
                self.explain_actual_impl_that_was_found(sub_placeholder,
                    sup_placeholder, has_sub, has_sup, expected_trait_ref,
                    actual_trait_ref, vid, expected_has_vid, actual_has_vid,
                    any_self_ty_has_vid, leading_ellipsis);
            let mut err =
                self.tcx().dcx().create_err(TraitPlaceholderMismatch {
                        span,
                        satisfy_span,
                        where_span,
                        dup_span,
                        def_id,
                        trait_def_id: self.tcx().def_path_str(trait_def_id),
                        actual_impl_expl_notes,
                    });
            let mut current_code = cause.code();
            let mut coroutine_def_id = None;
            loop {
                match current_code {
                    ObligationCauseCode::MatchImpl(inner_cause, _) => {
                        current_code = inner_cause.code();
                    }
                    ObligationCauseCode::BuiltinDerived(derived) => {
                        let self_ty =
                            derived.parent_trait_pred.skip_binder().self_ty();
                        if let ty::Coroutine(def_id, _) |
                                ty::CoroutineWitness(def_id, _) = self_ty.kind() {
                            coroutine_def_id = Some(*def_id);
                            break;
                        }
                        current_code = &derived.parent_code;
                    }
                    _ => break,
                }
            }
            if let Some(def_id) = coroutine_def_id {
                if self.tcx().trait_is_auto(trait_def_id) {
                    let c_span = self.tcx().def_span(def_id);
                    let descr = self.tcx().def_descr(def_id);
                    let trait_name = self.tcx().def_path_str(trait_def_id);
                    err.span_label(c_span,
                        ::alloc::__export::must_use({
                                ::alloc::fmt::format(format_args!("this {0} captures a value whose type is not `{1}`",
                                        descr, trait_name))
                            }));
                }
            }
            if self.tcx().is_fn_trait(trait_def_id) {
                let actual_self_ty =
                    self.cx.deeply_resolve_ignoring_regions(ty::TraitRef::new_from_args(self.cx.tcx,
                                trait_def_id, actual_args).self_ty());
                if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
                            && let Some(local_def_id) = closure_def_id.as_local() &&
                        let hir::Node::Expr(hir::Expr {
                            kind: hir::ExprKind::Closure(closure), .. }) =
                            self.tcx().hir_node_by_def_id(local_def_id) {
                    let body = self.tcx().hir_body(closure.body);
                    let expected_input_tys = expected_args.type_at(1);
                    if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
                        let suggestions: Vec<_> =
                            body.params.iter().zip(input_tys.iter()).filter_map(|(param,
                                            ty)|
                                        {
                                            if param.ty_span == param.pat.span &&
                                                    ty.is_suggestable(self.tcx(), false) {
                                                Some((param.pat.span.shrink_to_hi(),
                                                        ::alloc::__export::must_use({
                                                                ::alloc::fmt::format(format_args!(": {0}", ty))
                                                            })))
                                            } else { None }
                                        }).collect();
                        if !suggestions.is_empty() {
                            let msg =
                                if suggestions.len() == 1 {
                                    "consider adding an explicit type annotation to the closure's argument"
                                } else {
                                    "consider adding explicit type annotations to the closure's arguments"
                                };
                            err.multipart_suggestion(msg, suggestions,
                                Applicability::MaybeIncorrect);
                        }
                    }
                }
            }
            err
        }
    }
}#[instrument(level = "debug", skip(self))]
246    fn report_trait_placeholder_mismatch(
247        &self,
248        vid: Option<Region<'tcx>>,
249        cause: &ObligationCause<'tcx>,
250        sub_placeholder: Option<Region<'tcx>>,
251        sup_placeholder: Option<Region<'tcx>>,
252        trait_def_id: DefId,
253        expected_args: GenericArgsRef<'tcx>,
254        actual_args: GenericArgsRef<'tcx>,
255    ) -> Diag<'tcx> {
256        let span = cause.span;
257
258        let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
259            if let ObligationCauseCode::WhereClause(def_id, span)
260            | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *cause.code()
261                && def_id != CRATE_DEF_ID.to_def_id()
262            {
263                (
264                    true,
265                    Some(span),
266                    Some(self.tcx().def_span(def_id)),
267                    None,
268                    self.tcx().def_path_str(def_id),
269                )
270            } else {
271                (false, None, None, Some(span), String::new())
272            };
273
274        let expected_trait_ref = self.cx.deeply_resolve_ignoring_regions(
275            ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, expected_args),
276        );
277        let actual_trait_ref = self.cx.deeply_resolve_ignoring_regions(
278            ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args),
279        );
280
281        // Search the expected and actual trait references to see (a)
282        // whether the sub/sup placeholders appear in them (sometimes
283        // you have a trait ref like `T: Foo<fn(&u8)>`, where the
284        // placeholder was created as part of an inner type) and (b)
285        // whether the inference variable appears. In each case,
286        // assign a counter value in each case if so.
287        let mut counter = 0;
288        let mut has_sub = None;
289        let mut has_sup = None;
290
291        let mut actual_has_vid = None;
292        let mut expected_has_vid = None;
293
294        self.tcx().for_each_free_region(&expected_trait_ref, |r| {
295            if Some(r) == sub_placeholder && has_sub.is_none() {
296                has_sub = Some(counter);
297                counter += 1;
298            } else if Some(r) == sup_placeholder && has_sup.is_none() {
299                has_sup = Some(counter);
300                counter += 1;
301            }
302
303            if Some(r) == vid && expected_has_vid.is_none() {
304                expected_has_vid = Some(counter);
305                counter += 1;
306            }
307        });
308
309        self.tcx().for_each_free_region(&actual_trait_ref, |r| {
310            if Some(r) == vid && actual_has_vid.is_none() {
311                actual_has_vid = Some(counter);
312                counter += 1;
313            }
314        });
315
316        let actual_self_ty_has_vid =
317            self.tcx().any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);
318
319        let expected_self_ty_has_vid =
320            self.tcx().any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid);
321
322        let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid;
323
324        debug!(
325            ?actual_has_vid,
326            ?expected_has_vid,
327            ?has_sub,
328            ?has_sup,
329            ?actual_self_ty_has_vid,
330            ?expected_self_ty_has_vid,
331        );
332
333        let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
334            sub_placeholder,
335            sup_placeholder,
336            has_sub,
337            has_sup,
338            expected_trait_ref,
339            actual_trait_ref,
340            vid,
341            expected_has_vid,
342            actual_has_vid,
343            any_self_ty_has_vid,
344            leading_ellipsis,
345        );
346
347        let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch {
348            span,
349            satisfy_span,
350            where_span,
351            dup_span,
352            def_id,
353            trait_def_id: self.tcx().def_path_str(trait_def_id),
354            actual_impl_expl_notes,
355        });
356
357        let mut current_code = cause.code();
358        let mut coroutine_def_id = None;
359
360        loop {
361            match current_code {
362                ObligationCauseCode::MatchImpl(inner_cause, _) => {
363                    current_code = inner_cause.code();
364                }
365                ObligationCauseCode::BuiltinDerived(derived) => {
366                    let self_ty = derived.parent_trait_pred.skip_binder().self_ty();
367
368                    if let ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) =
369                        self_ty.kind()
370                    {
371                        coroutine_def_id = Some(*def_id);
372                        break;
373                    }
374
375                    current_code = &derived.parent_code;
376                }
377                _ => break,
378            }
379        }
380
381        if let Some(def_id) = coroutine_def_id {
382            if self.tcx().trait_is_auto(trait_def_id) {
383                let c_span = self.tcx().def_span(def_id);
384                let descr = self.tcx().def_descr(def_id);
385                let trait_name = self.tcx().def_path_str(trait_def_id);
386
387                err.span_label(
388                    c_span,
389                    format!("this {descr} captures a value whose type is not `{trait_name}`"),
390                );
391            }
392        }
393
394        // When the mismatched trait is an Fn-trait and the self type is a closure with
395        // unannotated parameters, suggest adding explicit type annotations. This turns
396        // the confusing lifetime-generality error into an actionable hint, e.g.:
397        //   |buf|  →  |buf: &mut [u8]|
398        if self.tcx().is_fn_trait(trait_def_id) {
399            let actual_self_ty = self.cx.deeply_resolve_ignoring_regions(
400                ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, actual_args).self_ty(),
401            );
402            if let ty::Closure(closure_def_id, _) = *actual_self_ty.kind()
403                && let Some(local_def_id) = closure_def_id.as_local()
404                && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) =
405                    self.tcx().hir_node_by_def_id(local_def_id)
406            {
407                let body = self.tcx().hir_body(closure.body);
408                // For Fn traits, args[1] is the tupled input types (e.g. `(&mut [u8],)`).
409                let expected_input_tys = expected_args.type_at(1);
410                if let ty::Tuple(input_tys) = *expected_input_tys.kind() {
411                    let suggestions: Vec<_> = body
412                        .params
413                        .iter()
414                        .zip(input_tys.iter())
415                        .filter_map(|(param, ty)| {
416                            // ty_span == pat.span means no explicit type annotation was written.
417                            if param.ty_span == param.pat.span
418                                && ty.is_suggestable(self.tcx(), false)
419                            {
420                                Some((param.pat.span.shrink_to_hi(), format!(": {ty}")))
421                            } else {
422                                None
423                            }
424                        })
425                        .collect();
426                    if !suggestions.is_empty() {
427                        let msg = if suggestions.len() == 1 {
428                            "consider adding an explicit type annotation to the closure's argument"
429                        } else {
430                            "consider adding explicit type annotations to the closure's arguments"
431                        };
432                        err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
433                    }
434                }
435            }
436        }
437
438        err
439    }
440
441    /// Add notes with details about the expected and actual trait refs, with attention to cases
442    /// when placeholder regions are involved: either the trait or the self type containing
443    /// them needs to be mentioned the closest to the placeholders.
444    /// This makes the error messages read better, however at the cost of some complexity
445    /// due to the number of combinations we have to deal with.
446    fn explain_actual_impl_that_was_found(
447        &self,
448        sub_placeholder: Option<Region<'tcx>>,
449        sup_placeholder: Option<Region<'tcx>>,
450        has_sub: Option<usize>,
451        has_sup: Option<usize>,
452        expected_trait_ref: ty::TraitRef<'tcx>,
453        actual_trait_ref: ty::TraitRef<'tcx>,
454        vid: Option<Region<'tcx>>,
455        expected_has_vid: Option<usize>,
456        actual_has_vid: Option<usize>,
457        any_self_ty_has_vid: bool,
458        leading_ellipsis: bool,
459    ) -> Vec<ActualImplExplNotes<'tcx>> {
460        // The weird thing here with the `maybe_highlighting_region` calls and the
461        // the match inside is meant to be like this:
462        //
463        // - The match checks whether the given things (placeholders, etc) appear
464        //   in the types are about to print
465        // - Meanwhile, the `maybe_highlighting_region` calls set up
466        //   highlights so that, if they do appear, we will replace
467        //   them `'0` and whatever. (This replacement takes place
468        //   inside the closure given to `maybe_highlighting_region`.)
469        //
470        // There is some duplication between the calls -- i.e., the
471        // `maybe_highlighting_region` checks if (e.g.) `has_sub` is
472        // None, an then we check again inside the closure, but this
473        // setup sort of minimized the number of calls and so form.
474
475        let highlight_trait_ref = |trait_ref| Highlighted {
476            tcx: self.tcx(),
477            highlight: RegionHighlightMode::default(),
478            value: trait_ref,
479            ns: Namespace::TypeNS,
480        };
481
482        let same_self_type = actual_trait_ref.self_ty() == expected_trait_ref.self_ty();
483
484        let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
485        expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
486        expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
487
488        let passive_voice = match (has_sub, has_sup) {
489            (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
490            (None, None) => {
491                expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
492                match expected_has_vid {
493                    Some(_) => true,
494                    None => any_self_ty_has_vid,
495                }
496            }
497        };
498
499        let (kind, ty_or_sig, trait_path) = if same_self_type {
500            let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
501            self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
502
503            if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
504            {
505                let closure_sig = self_ty.map(|closure| {
506                    if let ty::Closure(_, args) = closure.kind() {
507                        self.tcx()
508                            .signature_unclosure(args.as_closure().sig(), rustc_hir::Safety::Safe)
509                    } else {
510                        ::rustc_span::macros::bug_impl(None,
    format_args!("type is not longer closure"), Location::caller());bug!("type is not longer closure");
511                    }
512                });
513                (
514                    ActualImplExpectedKind::Signature,
515                    TyOrSig::ClosureSig(closure_sig),
516                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
517                )
518            } else {
519                (
520                    ActualImplExpectedKind::Other,
521                    TyOrSig::Ty(self_ty),
522                    expected_trait_ref.map(|tr| tr.print_only_trait_path()),
523                )
524            }
525        } else if passive_voice {
526            (
527                ActualImplExpectedKind::Passive,
528                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
529                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
530            )
531        } else {
532            (
533                ActualImplExpectedKind::Other,
534                TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
535                expected_trait_ref.map(|tr| tr.print_only_trait_path()),
536            )
537        };
538
539        let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
540            (Some(n1), Some(n2)) => {
541                (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
542            }
543            (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
544            (None, None) => {
545                if let Some(n) = expected_has_vid {
546                    (ActualImplExpectedLifetimeKind::Some, n, 0)
547                } else {
548                    (ActualImplExpectedLifetimeKind::Nothing, 0, 0)
549                }
550            }
551        };
552
553        let note_1 = ActualImplExplNotes::new_expected(
554            kind,
555            lt_kind,
556            leading_ellipsis,
557            ty_or_sig,
558            trait_path,
559            lifetime_1,
560            lifetime_2,
561        );
562
563        let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
564        actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
565
566        let passive_voice = match actual_has_vid {
567            Some(_) => any_self_ty_has_vid,
568            None => true,
569        };
570
571        let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
572        let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
573        let has_lifetime = actual_has_vid.is_some();
574        let lifetime = actual_has_vid.unwrap_or_default();
575
576        let note_2 = if same_self_type {
577            ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime }
578        } else if passive_voice {
579            ActualImplExplNotes::ButActuallyImplementedForTy {
580                trait_path,
581                ty,
582                has_lifetime,
583                lifetime,
584            }
585        } else {
586            ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
587        };
588
589        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [note_1, note_2]))vec![note_1, note_2]
590    }
591}