Skip to main content

rustc_trait_selection/error_reporting/infer/nice_region_error/
placeholder_error.rs

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